Linux进程间通信——消息队列

消息队列是存放消息的链表,存在于内核空间,由系统内核维护

消息队列的特点:
1. 消息队列可以实现消息的随机查询,满足队列的特点但不一定要以先进先出的次序读取,可以按消息的类型读取;
2.消息队列允许一个或多个进程向它写入或者读取消息;
3.与无名管道、有名管道一样,从消息队列中读出消息,消息队列中数据会被删除;
4.消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级;
5. 只有内核重启或人工删除时,该消息才会被删除,若不人工删除消息队列,消息队列会一直存在于内存中。

消息队列标识符,来标识消息队列。消息队列在整个 系统中是唯一的。
在Linux操作系统中消息队列限制值如下:
   1. 消息队列个数最多为16个
   2. 消息队列总容量最多为16384字节
   3.每个消息内容最多为8192字节
System V提供的IPC通信机制需要一个key值,通过key 值就可在系统内获得一个唯一的消息队列。
key值可以是人为指定的,也可以通过ftok函数获得。
Linux进程间通信——消息队列_第1张图片

/*
   //1.创建消息队列
   int msgget(key_t key, int msgflg);
   
       msgflg: 标识函数的行为及消息队列的权限,其取值如下
         'IPC_CREAT':创建消息队列。 
         'IPC_EXCL': 检测消息队列是否存在。
    位或权限位:消息队列位或权限位后可以设置消息队列的访问权限,但可执行权限未使用。一般是0666
     返回值: 成功返回消息队列的标识符 ;失败返回
     
   //2.写入消息
    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    
        msgflg:函数的控制属性,其取值如下:
             '0': msgsnd()调用阻塞直到条件满足为止。
            'IPC_NOWAIT': 若消息没有立即发送则调用该函数的进程会立即返回。
     返回值:成功返回0,失败返回-1。
     
    //3.读取消息        
     ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
     
          msgtyp:消息的类型:
            msgtyp = 0:返回队列中的第一个消息。
            msgtyp > 0:返回队列中消息类型为 msgtyp 的消息(常用)。
            msgtyp < 0:返回队列中消息类型值小于或等于 msgtyp 绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。在获取某类型消息的时候,若队列中有多条   此类型的消息,则获取最先添加的消息,即先进先出原则。
         msgflg:函数的控制属性:
           '0': msgrcv() 调用阻塞直到接收消息成功为止。
           'MSG_NOERROR': 若返回的消息字节数比 nbytes 字节数多,则消息就会截短到 nbytes 字节,且不通知消息发送进程。
           IPC_NOWAIT: 调用进程会立即返回。若没有收到消息则立即返回 -1。
      返回值: 成功读取消息的长度; 失败:-1
      
      //4.消息队列控制
      int msgctl(int msqid, int cmd, struct msqid_ds *buf);
      
        cmd::
             'IPC_RMID' :删除消息队列。从系统中删除给消息队列以及仍在该队列上的所有数据,这种删除立即生效。仍在使用这一消息\
             队列的其他进程在它们下一次试图对此队列进行操作时,将出错,并返回EIDRM。 此命令只能由如下两种进程执行:
                1.其有效用户ID等于msg_perm.cuid或msg_perm.guid的进程。
                2.另一种是具有超级用户特权的进程。
             'IPC_SET' :设置消息队列的属性。按照buf指向的结构中的值,来设置此队列的msqid_id结构。该命令的执行特权与上一个相同。
             'IPC_STAT':读取消息队列的属性。取得此队列的msqid_ds结构,并存放在buf*中。
             'IPC_INFO':读取消息队列基本情况。
        buf:队列中的内容,一般为NULL。
*/
/*msg_send.c*/
#include
#include 
#include 
#include 
#include


struct msgbuf{
        long mtype;//消息类型(>0)
        char mtext[128];//消息文本
};

int main()
{
        key_t key;
        struct msgbuf send = {888,"this message from send"};
        struct msgbuf getbuf;
        //获取key值
        //key_t ftok(const char *pathname, int proj_id);
        key = ftok(".",'z');//   路径          id号
        if(key == -1){
            printf("ftok error\n");
         }
        printf("key:%x\n",key);
        //创建消息队列
        int msqid = msgget(key,IPC_CREAT|0666);
        if(msqid == -1){

            printf("msg creat failed\n");
        }
        //将消息类型为'888'的信息写入队列,'0'以阻塞的方式写入
        if( msgsnd(msqid,&send,strlen(send.mtext),0) == -1){

            printf("msgsend error\n");
        }
        //从队列中读取消息类型为'666'的信息,'0',以阻塞的方式读
        msgrcv(msqid,&getbuf,128,666,0);
        printf("%s\n",getbuf.mtext);
        //删除队列
        msgctl(msqid,IPC_RMID,NULL);
        
        return 0;
 } 
/*msg_get.c*/
#include
#include 
#include 
#include 
#include 

struct msgbuf{
        long mtype;//消息类型(>0)
        char mtext[128];//消息文本
};
 
int main()
{
        key_t key;

        struct msgbuf send = {666,"this message from get"};
        struct msgbuf getbuf;

        key = ftok(".",'z');
        if(key == -1){
            printf("ftok error\n");
         }
        printf("key:%x\n",key);
        //创建消息队列
        int msqid = msgget(key,IPC_CREAT|0666);
        if(msqid == -1){

          printf("msg creat failed\n");
        }
         //获取消息类型为'888' 的消息
         msgrcv(msqid,&getbuf,128,888,0);
         printf("%s\n",getbuf.mtext);
         //发送消息类型为'666'的消息
         msgsnd(msqid,&send,strlen(send.mtext),0);
         //删除队列
         msgctl(msqid,IPC_RMID,NULL);

          return 0;
}

                         

你可能感兴趣的:(Linux,linux)