Linux_4 消息队列

1.基础概念

消息队列,Unix的通信机制之一,可以理解为是一个存放消息(数据)容器。将消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序。

消息队列本质上是位于内核空间的链表,链表的每个节点都是一条消息。每一条消息都有自己的消息类型,消息类型用整数来表示,而且必须大于 0。每种类型的消息都被对应的链表所维护。

ftok:

消息队列具有一个唯一的键值,或称引用标识符、消息队列的ID号,通过使用ftok()函数获取,函数原型:

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(char *pathname, char proj);

获取成功返回消息队列的键值,失败返回-1。

参数pathname为一任意存在的路径名,参数proj为1~255之间的任一数字,ftok根据路径名,提取文件信息,再根据这些文件信息及proj的值合成key。(注:此段参考:ftok()函数深度解析)。

ftock()函数并不直接对消息队列操作,生成的键值用于msgget()函数使用,该函数用于创建或打开一个消息队列,其函数原型如下:

msgget:

运行成功则返回消息队列的引用标识符(ID),失败则返回-1。

 

参数keyftok()产生的键值,参数msgflg是一些标志位,可以取IPC_CREAT(没有消息队列就创建,有就打开)IPC_EXCLIPC_NOWAIT或三者的逻辑或结果

扫描二维码关注公众号,回复: 15954726 查看本文章

在以下两种情况下,msgget()将创建一个新的消息队列:

  • 如果没有消息队列与键值key相对应,且msgflg中包含了IPC_CREAT标志位
  • key参数为IPC_PRIVATE

msgsnd:  

 struct msgbuf 
 {
      long mtype;       /* message type, must be > 0 */
      char mtext[1];    /* message data */ 所要发送的信息
 };                     // 可以是其他类型,int double

//所以信息大小 sizeof(buff) - sizeof(buff.mtype)

msgrcv:

 msgctl

 

2.父子进程消息队列 

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>

#define MY_TYPE 9527

int main(void)
{
        int msgid; // 返回消息队列的描述符
	    pid_t pid;
        // 定义消息内容
        struct msgbuf
        {
             long mtype;
             char mtext[100];
             int number;
        }; 
        struct msgbuf buff;

        msgid = msgget(IPC_PRIVATE, IPC_CREAT|0660); // 创建消息队列

	    pid = fork();      // 创建进程
        if(pid > 0)        // 父进程
	    {    
               sleep(5);          
               buff.mtype = MY_TYPE;
               printf("please enter the string you want to send:\n");
               gets(buff.mtext);
               printf("please enter a number you want to send:\n");
               scanf("%d", &buff.number); // 
               msgsnd(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), 0); 
               //msgsnd 发送消息  1.返回消息队列的描述符  2.指针,指向自定义结构体  3.内容大小
               waitpid(pid, NULL, 0);     // 等待子进程结束
	    }
	    else if(pid == 0)  // 子进程
	    {
               printf("child process is waiting for message:\n");    // 消息类型
               msgrcv(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), MY_TYPE, 0);   
               // msgrcv 接收信息  buff 复制的父进程的用于存放收到的信息  接收信息类型与输入信息类型相同
               printf("child process read from msg: %s, %d\n", buff.mtext, buff.number);
               msgctl(msgid, IPC_RMID, NULL);  // 删除
	    }
	    else
	           perror("fork");

	    return 0;
	
}

3.非亲属关系进程消息队列 

send_msg.c

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>

#define MY_TYPE 9527
#define MY_KEY 1314       //也可以使用ftok,避免冲突

// 定义消息内容
struct msgbuf
{
     long mtype;
     char mtext[100];
     int number;
}; 

int main(void)
{
        int msgid;
        struct msgbuf buff;
        msgid = msgget(MY_KEY, 0666|IPC_CREAT);	 // 创建消息队列
         
        buff.mtype = MY_TYPE;
        printf("please enter the string you want to send:\n");
        gets(buff.mtext);
        printf("please enter a number you want to send:\n");
        scanf("%d", &buff.number);
        msgsnd(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), 0); //msgsnd发送消息  指针  内容大小

        return 0;
	
}

recv_msg.c

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>

#define MY_TYPE 9527
#define MY_KEY 1314


// 定义消息内容
struct msgbuf
{
     long mtype;
     char mtext[100];
     int number;
}; 

int main(void)
{
        int msgid;
        struct msgbuf buff;
        msgid = msgget(MY_KEY, 0666|IPC_CREAT);	 // 创建消息队列
         
        while(1)
        {
            printf("process is waiting for msg:\n");
            msgrcv(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), MY_TYPE, 0)
            prinrf("process read from msg: %s, %d\n", buff.mtext, buff.number);
        }
        msgctl(msgid, IPC_RMID, NULL);
        return 0;
	
}

猜你喜欢

转载自blog.csdn.net/qq_44177768/article/details/127824498
今日推荐