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

本文主要是介绍嵌入式学习第二十四天!(进程间通信:消息队列、共享内存、信号灯),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

进程间的通信:

  消息队列共享内存信号灯

     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.chinasem.cn/article/775226

相关文章

Windows的CMD窗口如何查看并杀死nginx进程

《Windows的CMD窗口如何查看并杀死nginx进程》:本文主要介绍Windows的CMD窗口如何查看并杀死nginx进程问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows的CMD窗口查看并杀死nginx进程开启nginx查看nginx进程停止nginx服务

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Java中常见队列举例详解(非线程安全)

《Java中常见队列举例详解(非线程安全)》队列用于模拟队列这种数据结构,队列通常是指先进先出的容器,:本文主要介绍Java中常见队列(非线程安全)的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一.队列定义 二.常见接口 三.常见实现类3.1 ArrayDeque3.1.1 实现原理3.1.2

Java进程CPU使用率过高排查步骤详细讲解

《Java进程CPU使用率过高排查步骤详细讲解》:本文主要介绍Java进程CPU使用率过高排查的相关资料,针对Java进程CPU使用率高的问题,我们可以遵循以下步骤进行排查和优化,文中通过代码介绍... 目录前言一、初步定位问题1.1 确认进程状态1.2 确定Java进程ID1.3 快速生成线程堆栈二、分析

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

C++ RabbitMq消息队列组件详解

《C++RabbitMq消息队列组件详解》:本文主要介绍C++RabbitMq消息队列组件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C++客户端库4. A

golang实现延迟队列(delay queue)的两种实现

《golang实现延迟队列(delayqueue)的两种实现》本文主要介绍了golang实现延迟队列(delayqueue)的两种实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录1 延迟队列:邮件提醒、订单自动取消2 实现2.1 simplChina编程e简单版:go自带的time

SpringCloud整合MQ实现消息总线服务方式

《SpringCloud整合MQ实现消息总线服务方式》:本文主要介绍SpringCloud整合MQ实现消息总线服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、背景介绍二、方案实践三、升级版总结一、背景介绍每当修改配置文件内容,如果需要客户端也同步更新,

Python多进程、多线程、协程典型示例解析(最新推荐)

《Python多进程、多线程、协程典型示例解析(最新推荐)》:本文主要介绍Python多进程、多线程、协程典型示例解析(最新推荐),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 目录一、multiprocessing(多进程)1. 模块简介2. 案例详解:并行计算平方和3. 实现逻

C#通过进程调用外部应用的实现示例

《C#通过进程调用外部应用的实现示例》本文主要介绍了C#通过进程调用外部应用的实现示例,以WINFORM应用程序为例,在C#应用程序中调用PYTHON程序,具有一定的参考价值,感兴趣的可以了解一下... 目录窗口程序类进程信息类 系统设置类 以WINFORM应用程序为例,在C#应用程序中调用python程序