【Linux之进程间通信】07.Linux进程通信 - 消息队列

 
【Linux之进程间通信】

项目代码获取:https://gitee.com/chenshao777/linux-processes.git
(麻烦点个免费的Star哦,您的Star就是我的写作动力!)

07.消息队列

1.创建消息队列

int msgget(key_t key, int msgflg);
参数 含义
key 生成msgid相关的key值
msgflg 权限

需要包含头文件

#include 
#include 
#include 

2.删除消息队列对象

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数 含义
msqid msgid
cmd 命令参数(IPC_RMID:删除,IPC_STAT:查看状态…)
buf cmd=IPC_SET时该参数用于设置属性

需要包含头文件

#include 
#include 
#include 

3.写消息队列

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数 含义
msqid msgid
msgp msg结构体(至少包括type、text两个成员)
msgsz msg结构体中text数组
msgflg 0:阻塞至消息写完
IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回
IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。

需要包含头文件

#include 
#include 
#include 

4.读消息队列

ssize_t msgrcv(int msqid, 
				void *msgp, 
				size_t msgsz, 
				long msgtyp,
				int msgflg);
参数 含义
msqid msgid
msgp 接收缓冲区
msgsz 接收的数据长度
msgtyp 0:接收第一个消息
>0:接收类型等于msgtyp的第一个消息
<0:接收类型等于或者小于msgtyp绝对值的第一个消息
msgflg 0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待
IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG
IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息
IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字节,则把该消息截断,截断部分将被丢弃

需要包含头文件

#include 
#include 
#include 

5.消息队列特点

  1. 链式队列,不用初始化大小
  2. 写入和读取时都可以阻塞(可以不通过发送信号让接收方接收)
  3. 数据可以赋予标注类型(比如湿度,电压等)
  4. 可以通过数据的类型特点实现多个进程通过一个消息队列进行通信

6.两个进程间通信代码示例

进程1

#include 
#include 
#include 
#include 
#include 
#include 
#include 

//消息结构体
struct msg_struct{
    long type;
    char text[128];
};

void handler(int sig)
{
    return;
}

int main(int argc, char *argv[])
{
    int msg_id;
    int key;
    key = ftok("./a.c",1);

    //亲缘进程消息队列
    msg_id = msgget(key, IPC_CREAT | 0777); 
    if(msg_id < 0){
        printf("创建消息队列失败\n");
    }

    //初始化消息
    struct msg_struct msgsend, msgrecv;

    int pid;
    pid = fork();
    if(pid > 0){
        msgsend.type = 100;

        printf("父进程负责发送\n");
        while(1){
            //从键盘获取
            fgets(msgsend.text, 128, stdin);
            //写入信号队列
            msgsnd(msg_id, (const void*)&msgsend, 128, 0);
        }
    }
    else if(pid == 0){
        printf("子进程负责接收\n");
        while(1)
        {
            memset(msgrecv.text,0,128);
            msgrcv(msg_id,(void*)&msgrecv,128,200,0);
            printf("接收到:%s",msgrecv.text);    
        }
    }

    return 0;
}

进程2

#include 
#include 
#include 
#include 
#include 
#include 
#include 

//消息结构体
struct msg_struct{
    long type;
    char text[128];
};

void handler(int sig)
{
    return;
}

int main(int argc, char *argv[])
{
    int msg_id;
    int key;
    key = ftok("./a.c",1);

    //亲缘进程消息队列
    msg_id = msgget(key, IPC_CREAT | 0777); 
    if(msg_id < 0){
        printf("创建消息队列失败\n");
    }

    //初始化消息
    struct msg_struct msgsend, msgrecv;

    int pid;
    pid = fork();
    if(pid > 0){
        msgsend.type = 200;
        printf("父进程负责发送\n");
        while(1){
            //从键盘获取
            fgets(msgsend.text, 128, stdin);
            //写入信号队列
            msgsnd(msg_id, (const void*)&msgsend, 128, 0);
        }
    }
    else if(pid == 0){
        printf("子进程负责接收\n");
        while(1)
        {
            memset(msgrecv.text,0,128);
            msgrcv(msg_id,(void*)&msgrecv,128,100,0);
            printf("接收到:%s",msgrecv.text);    
        }
    }

    return 0;
}

运行结果:

进程1

hc@hc-vm:~/Linux_ARM/git/linux-processes/06.消息队列$ ./write 
父进程负责发送
子进程负责接收
接收到:123
接收到:456
abc
aaa

进程2

hc@hc-vm:~/Linux_ARM/git/linux-processes/06.消息队列$ ./read 
父进程负责发送
子进程负责接收
123
456
接收到:abc
接收到:aaa

你可能感兴趣的:(Linux进程间通信,linux,多进程,消息队列)