i.MX6ULL终结者进程间通信 System V消息队列

System V IPC包含三种进程间通信机制,有消息队列,信号灯(也叫信号量),共享内存。此外还有System V IPC的补充版本POSIX IPC,这两组IPC的通信方法基本一致,本章以System V IPC为例介绍Linux进程通信机制。
可以用命令“ipcs”查看三种IPC,“ipcrm”删除IPC对象。在i.MX6ULL终结者开发板终端输入“ipcs”查看系统中存在的IPC信息:
在这里插入图片描述

图 1

这些 IPC对象存在于内核空间,应用层使用IPC通信的步骤为:
在这里插入图片描述

图 2

1.获取 key值,内核会将 key值映射成IPC标识符,获取key值常用方法:
(1)在get调用中将IPC_PRIVATE常量作为key值。
(2)使用ftok()生成key。
2.执行IPC get调用,通过key获取整数IPC标识符id,每个id表示一个IPC对象。
接口	消息队列	共享内存	信号灯创建/打开对象	msgget()	shmget()	semget()

3.通过id访问IPC对象。
在这里插入图片描述

4.通过id控制IPC对象
在这里插入图片描述

创建这三种IPC对象都要先获取key值,然后根据key获取id,用到的函数如下:
ftok():获取key,定义如下:
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
参数含义:
pathname:路径名或文件名。
proj_id:同一个文件根据此值生成多个key值,int型或字符型,多个若想访问同一IPC对象,此值必须相同。
返回值:成功返回key值,失败返回-1。

下面介绍消息队列:
消息队列是类 unix系统中一种数据传输的机制,其他操作系统中也实现了这种机制,可见这种通信机制在操作系统中有重要地位。
Linux内核为每个消息队列对象维护一个msqid_ds,每个msqid_ds对应一个id,消息以链表形式存储,并且msqid_ds存放着这个链表的信息。
在这里插入图片描述

图 3

消息队列的特点:
1.发出的消息以链表形式存储,相当于一个列表,进程可以根据id向对应的“列表”增加和获取消息。
2.进程接收数据时可以按照类型从队列中获取数据。

消息队列的使用步骤:
1.创建key;
2.msgget()通过key创建(或打开)消息队列对象id;
3.使用msgsnd()/msgrcv()进行收发;
4.通过msgctl()删除ipc对象

通过msgget()调用获取到id后即可使用消息队列访问IPC对象,消息队列常用API如下:
msgget():获取IPC对象唯一标识id,定义如下:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
参数含义:
key:通过f tok或IPC_PRIVATE获取的key值;
msgflg:指定匹配的结构,通常使用 IPC_CREAT。

msgsnd():发送数据
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void msgp, size_t msgsz, int msgflg);
参数含义:
msqid:IPC对象对应的 id;
msgp:消息指针,消息包含类型和字段;
msgsz:传输字段的大小,不算消息中的类型type占的内容;
在终端输入“man msgsnd”查看定义。
用于传输的消息格式通常为一个结构体,名字可以自定义,例如:
struct msgbuf {
long mtype; /
message type, must be > 0 /
char mtext[1]; /
message data */
};
其中“mtype”为消息类型,mtext为字段。
msgflg:用于控制msgsnd的操作,填写非阻塞IPC_NOWAIT;
返回值:成功返回0,失败返回-1.

msgrcv():接收消息,定义如下:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数含义:
msqid:IPC对象对应的 id;
msgp:消息指针,消息包含类型和字段;
msgsz: 消息里的字段大小;
msgtyp:消息里的类型;
msgflg:位掩码,不止一个。
返回值:成功返回接收到的字段大小,错误返回-1。

msgctl():控制操作,删除消息队列对象等,定义如下:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数含义:
msqid:IPC对象对应的id;
cmd:对消息队列对象进行的操作,
IPC_STAT:将与消息队列关联的msqid_ds复制到buf;
IPC_RMID:删除消息队列对象及msqid_ds。
IPC_SET:把 buf更新到msqid_ds。
buf:描述消息队列的结构体msqid_ds。
实验代码在msg_que/目录下:路径为:11_Linux系统开发进阶\Linux系统编程_章节使用资料。
send进程(代码见send.c)将数据发送到消息队列,并指定消息类型type,QT进程接收指定type为1的消息。
send.c:

#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
 
struct msg_buf{
    long mtype;
    char mtext[32];
};
#define MSG_LEN sizeof(struct msg_buf)-sizeof(long)
 
int main(int argc, const char *argv[])
{
 
    key_t key;
    int msgid;
    int ret;
 
    key = ftok("/", 133);
    if(key==-1){
        perror("ftok");
        return -1;
    }
     
    msgid = msgget(key,IPC_CREAT|0666);
    if(msgid==-1){
        perror("msgget");
        return -1;
    }
 
    struct msg_buf m_buf;
 
    m_buf.mtype=1;
    strcpy(m_buf.mtext,"IPC message Queues 1");
    int re;
    re = msgsnd(msgid,&m_buf,MSG_LEN,0);
    if(re==-1){
        perror("msgsnd");
        return -1;
    }
    return 0;
}

交叉编译到开发板:arm-linux-gnueabihf-gcc -o send send.c,
运行./send,查看系统中的IPC对象:
在这里插入图片描述

图 4

Qt进程代码在Qrecv/文件夹下,
在这里插入图片描述

图 5

执行四次./send向消息队列发送4条消息,将Qt程序交叉编译后在yocto文件系统运行,连续点击“get”按钮接收,后台打印如下:
在这里插入图片描述

图 6

GUI界面显示如下:
在这里插入图片描述

图 7

可以发现Qt进程能够接收到数据,这就是消息队列的基本用法。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值