嵌入式学习第二十四天!(进程间通信:消息队列、共享内存、信号灯)

news2024/11/24 9:46:46

进程间的通信:

  消息队列共享内存信号灯

     1. IPC对象:内存文件

        1. ipcs:

            查看系统中的消息队列,共享内存、信号灯的信息

        2. ipcrm:

            删除消息队列、共享内存、信号灯

ipcrm -Q/-M/-S key
ipcrm -q/-m/-s 消息对立ID/共享内存ID/信号灯ID

1. 消息队列:

    1. 操作流程:

        创建消息队列 -> 发送消息 -> 接收消息

    2. 函数接口:

        1. ftok:
key_t ftok(const char *pathname, int proj_id);

          功能:根据pathname和proj_id生成一个key_t类型的key值,将来可以创建消息队列、共享内存、信号灯

          参数:

              pathename:文件路径

              proj_id:8位非0值

          返回值:

              成功返回key_t类型的IPC对象的key值
              失败返回-1 

        2. msgsnd:
int msgget(key_t key, int msgflg);

          功能:根据key值对象的IPC对象创建一个消息队列

          参数:

              key:IPC对象名字

              msgflg:IPC_CREAT    对象不存在就创建

                            IPC_EXCL       对象存在报错

                            IPC_CREAT | 0664

          返回值:

              成功返回消息队列ID
              失败返回-1

        3.  msgsnd:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

          功能:向消息队列中发送消息

          参数:

              msqid:消息队列的ID号

              msgp:发送消息空间的首地址

struct msgbuf
{
    int mtypes;    /* message type, must be > 0 */
    char mtext[1]  /* message data */
};

              msgz:发送消息内容的大小(不包含发送消息类型)

              msgflg:属性,默认位0

          返回值:

              成功返回0 
              失败返回-1 

        4. msgrcv:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

          功能:从消息队列中接收消息

          参数:

              msqid:消息队列的ID号

              msgp:存放接收到消息空间的首地址

              msgsz:最多接收消息的空间大小

              msgtype:想要接收消息的类型

              msgflg:属性,默认为0

          返回值:

              成功返回实际接收的字节数
              失败返回-1 

        5. msgctl:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

          功能:向消息队列发送一条cmd命令

          参数:

              msqid:消息队列的ID号

              cmd:IPC_RMID  删除消息队列

              buf:默认传NULL

        练习:

          利用消息队列实现clientA和clientB两个进程任务的全双工聊天功能

clientA.c

 #include "head.h"

key_t key;
int msgid = 0;
pthread_t atob;
pthread_t btoa;

struct msgbuf
{
	long mtype;
	char mtext[256];
};

void *thread_atob(void *arg)
{
	struct msgbuf sndmsg;
	while(1)
	{
		memset(&sndmsg, 0, sizeof(sndmsg));
		sndmsg.mtype = 100;
		gets(sndmsg.mtext);
		msgsnd(msgid, &sndmsg, sizeof(struct msgbuf)-sizeof(long), 0);
		
		if(strcmp(sndmsg.mtext, ".quit") == 0)
		{
			break;
		}
	}
	pthread_cancel(atob);
	return NULL;

}

void *thread_btoa(void *arg)
{
	struct msgbuf recmsg;
	while(1)
	{
		memset(&recmsg, 0, sizeof(recmsg));
		msgrcv(msgid, &recmsg, sizeof(recmsg)-sizeof(long), 200, 0);
		printf("RECV:%s\n", recmsg.mtext);

		if(strcmp(recmsg.mtext, ".quit") == 0)
		{
			break;
		}
	}
	pthread_cancel(btoa);
	return NULL;
}

int main(void)
{
	pthread_create(&atob, NULL, thread_atob, NULL);
	pthread_create(&btoa, NULL, thread_btoa, NULL);

	key = ftok(".", 'a');
	if(key == -1)
	{
		perror("fail to ftok");
		return -1;
	}

	msgid = msgget(key, IPC_CREAT | 0664);
	if(msgid == -1)
	{
		perror("fail to msgget");
		return -1;
	}

	pthread_join(atob, NULL);
	pthread_join(btoa, NULL);
		
	msgctl(msgid, IPC_RMID, NULL);

	return 0;
}

clientB.c

#include "head.h"

key_t key;
int msgid = 0;
pthread_t atob;
pthread_t btoa;

struct msgbuf
{
	long mtype;
	char mtext[256];
};


void *thread_btoa(void *arg)
{
	struct msgbuf sndmsg;
	while(1)
	{
		memset(&sndmsg, 0, sizeof(sndmsg));
		sndmsg.mtype = 200;
		gets(sndmsg.mtext);
		msgsnd(msgid, &sndmsg, sizeof(struct msgbuf)-sizeof(long), 0);
		
		if(strcmp(sndmsg.mtext, ".quit") == 0)
		{
			break;
		}
	}
	pthread_cancel(btoa);

	return NULL;
}

void *thread_atob(void *arg)
{
	struct msgbuf recmsg;
	while(1)
	{
		memset(&recmsg, 0, sizeof(recmsg));
		msgrcv(msgid, &recmsg, sizeof(recmsg)-sizeof(long), 100, 0);
		printf("RECV:%s\n", recmsg.mtext);
		
		if(strcmp(recmsg.mtext, ".quit") == 0)
		{
			break;
		}
	}
	pthread_cancel(atob);
	return NULL;
}

int main(void)
{
	pthread_create(&atob, NULL, thread_atob, NULL);
	pthread_create(&btoa, NULL, thread_btoa, NULL);
	
	key = ftok(".", 'a');
	if(key == -1)
	{
		perror("fail to ftok");
		return -1;
	}

	msgid = msgget(key, IPC_CREAT | 0664);
	if(msgid == -1)
	{
		perror("fail to msgget");
		return -1;
	}

	pthread_join(atob, NULL);
	pthread_join(btoa, NULL);
	
	msgctl(msgid, IPC_RMID, NULL);

	return 0;
}

2. 共享内存:

  进程间通信最高效的形式

  1. 操作方式:

        创建共享内存  ->  映射到共享内存中  ->  共享内存操作  ->  解除映射  ->  删除共享内存

  2. 函数接口:

        1. ftok:
key_t ftok(const char *pathname, int proj_id);

          功能:根据pathname和proj_id生成一个key_t类型的key值,将来可以创建消息队列、共享内存、信号灯

          参数:

              pathename:文件路径

              proj_id:8位非0值

          返回值:

              成功返回key_t类型的IPC对象的key值
              失败返回-1 

        2. shmget:
int shmget(key_t key, size_t size, int shmflg);

          功能:创建一个共享内存

          参数:

              key:IPC对象名称

              size:共享内存的大小

              shmflg:

                    IPC_CREAT

                    IPC_EXCL

          返回值:

              成功返回共享内存ID
              失败返回-1 

        3. shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);

          功能:将一个地址映射到共享内存中

          参数:

              shmid:共享内存ID号

              shmaddr:

                    NULL:让系统选择一个合适的地址映射

                    不为NULL:shmflg设定SHM_RND选择离给定地址最近的能够映射的地址进行映射,否则传递地址为4K的整数倍

        4. shmdt:
int shmdt(const void *shmaddr);

          功能:解除映射

          参数:

              shmaddr:映射的地址

          返回值:

              成功返回0 
              失败返回-1 

        5. shmctl:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

          功能:向共享内存发送命令

          参数:

              shmid:共享内存ID号

              cmd:IPC_RMID 删除共享内存

              buf:NULL

          返回值:

              成功返回0 
              失败返回-1

        练习:

              编写2个进程任务,write.c负责从终端接收字符串写入共享内存中,read.c负责将共享内存中的数据打印在终端

write.c

#include "head.h"

int main(void)
{
	key_t key;
	int shmid;
	char *pshm = NULL;
	
	key = ftok(".", 'a');
	if(key == -1)
	{
		perror("fail to ftok");
		return -1;
	}

	shmid = shmget(key, 4096, IPC_CREAT | 0664);
	if(shmid == -1)
	{
		perror("fail to shmget");
		return -1;
	}
	
	pshm = (char *)shmat(shmid, NULL, 0);
	if(pshm == NULL)
	{
		perror("fail to shmat");
		return -1;
	}
	
	while(1)
	{
		gets(pshm);
		if(!strcmp(pshm, ".quit"))
		{
			shmdt(pshm);
			break;
		}
	}
	shmctl(shmid, IPC_RMID, NULL);

	return 0;
}
#include "head.h"

int main(void)
{
	key_t key;
	int shmid;
	char *pshm = NULL;
	char *ptmp = NULL;

	key = ftok(".", 'a');
	if(key == -1)
	{
		perror("fail to ftok");
		return -1;
	}

	shmid = shmget(key, 4096, IPC_CREAT | 0664);
	if(shmid == -1)
	{
		perror("fail to shmget");
		return -1;
	}
	
	pshm = shmat(shmid, NULL, 0);
	ptmp = malloc(4096);	
	
	strcpy(ptmp, pshm);

	while(1)
	{
		if (strcmp(pshm, ptmp) == 0)
		{
			continue;
		}
		else
		{
            printf("%s\n", pshm);
            strcpy(ptmp, pshm);
        }

		if(!strcmp(pshm, ".quit"))
		{
			free(ptmp);
			shmdt(pshm);
			break;
		}
	}

	shmctl(shmid, IPC_RMID, NULL);

	return 0;
}

        在这里使用了一个ptmp和原来的pshm比较,从而实现了一个从终端写一个,接收一个,其实应该使用信号灯实现,但是在这里还没有学,所以先暂时使用这个来实现。如果不加判断的话,终端输出的结果如下所示:

        终端会一直持续打印共享内存中的数据,继而需要用到信号灯来实现,写一条,只接收一条

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1489203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jmeter系列(4) 线程属性详解

线程属性 线程组是配置压测策略的一个重要环节线程组决定了测试执行的请求数量 线程数 在这里线程数相当于一个虚拟用户每个线程数大约占内存1M特别注意⚠️ 单台机器最大线程数不要超过1000,不然可能会造成内存溢出 Ramp-Up时间 所有线程在多长时间内全部启动…

S7-1200PLC脉冲轴位置控制功能块优化(完整SCL源代码)

博途PLC 位置控制功能块常用应用,可以参考下面文章链接: 1、博途PLC脉冲轴绝对定位往复运动控制 https://rxxw-control.blog.csdn.net/article/details/135768878https://rxxw-control.blog.csdn.net/article/details/1357688782、脉冲轴位置控制功能块…

自测-5 Shuffling Machine(python版本)

文章预览: 题目翻译算法python代码oj反馈结果 题目 翻译 shuffle是用于随机化一副扑克牌的过程。由于标准的洗牌技术被认为是薄弱的,并且为了避免员工通过不适当的洗牌与赌徒合作的“内部工作”,许多赌场使用了自动洗牌机。你的任务是模拟一…

【LeetCode:225. 用队列实现栈 + 栈 | 队列】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

HTML5:七天学会基础动画网页5

CSS3渐变 (可以给背景颜色设置一个渐变的效果) 线性渐变:Linear Gradients(从直线上向远处见面) 语法: background:linear-gradient(direction,color-stop1,color-stop2…); direction:方向 to left, to right, 90deg 径向渐变:Radial …

HM_2019在面积不变情况下编辑网格

首先,应该保存其形状,计算他的面积。让面积不变作为一个约束,然后进行网格的形变。

HTML5:七天学会基础动画网页7

CSS3高级特效 2D转换方法 移动:translate() 旋转:rotate() 缩放:scale() 倾斜:skew() 属性:transform 作用:对元素进行移动,旋转,缩放,倾斜。 2D移动 设定元素从当前位置移动到给定位置(x,y) 方法 说明 translate(x,y) 2D转换 沿X轴和Y轴移…

什么是张量?如何理解张量?

一、张量概念 张量(tensor)是一个多维数组,它是向量(一维数组)和矩阵(二维数组)的推广。在数学和物理学中,张量是一种广泛应用的概念,用来描述物理量在空间中的分布和变…

VMware之VSAN

VMware VSAN特点 聚合了虚拟化管理程序的极其简单的存储软件 1、完全式:全都是固态硬盘 2、混合式存储解决方案: →磁盘(硬盘) →基于闪存的磁盘(固态硬盘) 3、横向扩展体系: 增加主机数量 4、…

uniapp实现进度条组件

首先&#xff0c;在uniapp项目中创建一个自定义组件&#xff0c;可以命名为Progress.vue。在Progress.vue中&#xff0c;编写如下代码&#xff1a; <template><view class"progress"><view class"progress-bar" :style"{width: progr…

水牛社软件是真的吗?

软件是真的&#xff0c;不过毕竟是为了赚钱或者获取资源而买的&#xff0c;所以大部分只关心能赚多少钱吧 说实话&#xff0c;我用了2年了&#xff0c;一些独立的项目还有群&#xff0c;有一月挣几千上万的&#xff0c;有一月赚几百的 软件是一个集合体&#xff0c;不是像很多…

Html基础标签以及属性和用法

HTML基础 超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language&#xff0c;简称&#xff1a;HTML&#xff09;是一种用于创建网页的标准标记语言。 您可以使用 HTML 来建立自己的 WEB 站点&#xff0c;HTML 运行在浏览器上&#xff0c;由浏览器来解析。 HTM…

考研英语语法(句子成分)

目录 1.主句的成分&#xff1a; 2.化妆后句子的成分&#xff1a; 3.句子的基本结构&#xff1a; 4.句子成分表 5.复杂句型总结 1.并列句&#xff08;是由并列连词连接两个或两个以上的句子&#xff0c;用逗号隔开&#xff09; 2.名词性从句&#xff08;名词在句中充当成…

【Vue】探究 Vue 2 与 Vue 3 生命周期:变化与延续

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

MWC 2024 | 广和通携手意法半导体发布智慧家居解决方案

世界移动通信大会2024期间&#xff0c;广和通携手横跨多重应用领域、全球排名前列的半导体公司意法半导体&#xff08;STMicroelectronics&#xff0c;以下简称ST&#xff1b;纽约证券交易所代码&#xff1a;STM&#xff09;发布支持Matter协议的智慧家居解决方案。该方案在广和…

b站小土堆pytorch学习记录—— P15 Dataloader的使用

文章目录 一、前置知识1.dataloader简要介绍2.dataloader 官方文档&#xff08;翻译后&#xff09; 二、DataLoader的使用 一、前置知识 1.dataloader简要介绍 DataLoader 是 PyTorch 中用于加载数据的实用工具&#xff0c;它可以处理数据集的批量加载、数据集的随机打乱、多…

面试经典150题 -- 回溯 (总结)

总的链接 : 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 17 . 电话号码的字母组合 1 . 先创建一个下标 与 对应字符串映射的数组&#xff0c;这里使用hash表进行映射也是可以的 &#xff1b; 2 . 对于回溯 &#xff0c;…

【DUSt3R】2张图2秒钟3D重建

【DUSt3R】2张图2秒钟3D重建 1. DUSt3R是一种用于稠密和无约束立体三维重建的方法,其实现步骤如下:2. 实际运行效果3. 运行结果4. 自问自答4.1 为社么这里要是使用transform模型呢?4.2 CroCo(通过跨视图完成3D视觉任务的自我监督预训练的一个研究)在DUSt3R的作用是什么,为…

蓝桥杯集训·每日一题2024 (差分)

前言&#xff1a; 差分笔记以前就做了&#xff0c;在这我就不再写一遍了&#xff0c;直接上例题。 例题&#xff1a; #include<bits/stdc.h> using namespace std; int a[10009],b[100009]; int main(){int n,ans10,ans20;cin>>n;for(int i1;i<n;i){cin>>…

凸优化和非凸优化

在数学中一个非凸的最优化问题是什么意思&#xff1f; 1、凸优化和非凸优化的定义 2、凸优化&#xff1a;相对简单 在凸集中&#xff0c;有个基本理论&#xff0c;那就是任意局部最优解一定是全局最优解。基于这个性质&#xff0c;设计一个简单的局部算法&#xff0c;比如 贪…