程序员人生 网站导航

Linux消息队列实践(1)

栏目:php教程时间:2014-12-08 08:22:08

消息队列基本概念

    消息队列提供了1个从1个进程向另外1个进程发送1块数据的方法(仅局限与本机)

    每一个数据块都被认为是有1个类型,接收者进程接收的数据块可以有不同的类型值

    消息队列也有管道1样的不足,就是每一个消息的最大长度是有上限的(MSGMAX),每一个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有1个上限(MSGMNI)

 

管道 vs. 消息队列:

管道: 流管道          消息: 有边界

   先进先出            可以落后入、先出来

 

消息队列大小3大限制

   cat /proc/sys/kernel/msgmax  #最大消息长度限制

   cat /proc/sys/kernel/msgmnb  #消息队列总的字节数

   cat /proc/sys/kernel/msgmni  #消息条目数

 

 

IPC对象数据结构

   内核为每一个IPC对象保护1个数据结构

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct ipc_perm  
  2. {  
  3.     key_t          __key;       /* Key supplied to msgget(2) */  
  4.     uid_t          uid;         /* Effective UID of owner */  
  5.     gid_t          gid;         /* Effective GID of owner */  
  6.     uid_t          cuid;        /* Effective UID of creator */  
  7.     gid_t          cgid;        /* Effective GID of creator */  
  8.     unsigned short mode;        /* Permissions */  
  9.     unsigned short __seq;       /* Sequence number */  
  10. };  

 

消息队列独有的结构

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct msqid_ds  
  2. {  
  3.     struct ipc_perm msg_perm;     /* Ownership and permissions */  
  4.     time_t          msg_stime;    /* Time of last msgsnd(2) */  
  5.     time_t          msg_rtime;    /* Time of last msgrcv(2) */  
  6.     time_t          msg_ctime;    /* Time of last change */  
  7.     unsigned long   __msg_cbytes; /* Current number of bytes in 
  8.                                                 queue (nonstandard) */  
  9.     msgqnum_t       msg_qnum;     /* Current number of messages 
  10.                                                 in queue */  
  11.     msglen_t        msg_qbytes;   /* Maximum number of bytes 
  12.                                                 allowed in queue */  
  13.     pid_t           msg_lspid;    /* PID of last msgsnd(2) */  
  14.     pid_t           msg_lrpid;    /* PID of last msgrcv(2) */  
  15. };  

 

消息队列在内核中的表示


消息队列函数示例

msgget函数 

功能:用来创建访问1个消息队列

原型:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int msgget(key_t key, int msgflg);  

参数:

    key: 某个消息队列的名字

    msgflg:由9个权限标志构成,如0644,它们的用法和创建文件时使用的mode模式标志是1样的(但是消息队列没有x(履行)权限)

 

返回值:

   成功返回消息队列编号,即该消息队列的标识码;失败返回⑴

 

编程实践

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //实践1:  IPC_PRIVATE:宏,值为0  
  2. int main()  
  3. {  
  4.   //IPC_PRIVATE每次创建的消息队列的描写符都是不同的!  
  5.   //因此,计时MessageID(key)传送给其他进程(除非有关联的进程),  
  6.   //其他进程也没法使用该消息队列(血缘fork除外)  
  7.     int msgid = msgget(IPC_PRIVATE,0666);  
  8.     if (msgid < 0)  
  9.     {  
  10.         //如果消息队列不存在,则打开毛病,errno=ENOENT  
  11.         if (errno == ENOENT)  
  12.         {  
  13.             cout << "ENOENT" << endl;  
  14.         }  
  15.         err_exit("mesget error");  
  16.     }  
  17.     else  
  18.     {  
  19.         cout << "msgid = " << msgid << endl;  
  20.     }  
  21.   
  22.     return 0;  
  23. }  
  24. /** 
  25.   IPC_PRIVATE创建的消息队列,只能用在与当前进程有关系的进程中使用! 
  26. */  


[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //实践2:  IPC_CREAT  
  2. int main()  
  3. {  
  4.     //指定IPC_CREAT,则1定会创建消息队列  
  5.     int msgid = msgget(0x1235,0666|IPC_CREAT);  
  6.     if (msgid < 0)  
  7.     {  
  8.         //如果消息队列不存在,则打开毛病,errno=ENOENT  
  9.         if (errno == ENOENT)  
  10.         {  
  11.             cout << "ENOENT" << endl;  
  12.         }  
  13.         err_exit("mesget error");  
  14.     }  
  15.     else  
  16.     {  
  17.         cout << "msgid = " << msgid << endl;  
  18.     }  
  19.   
  20.     return 0;  
  21. }  


[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //实践3:  IPC_CREAT|IPC_EXCL  
  2. int main()  
  3. {  
  4.     //指定IPC_EXCL, 如果已存在,则报告文件已存在(毛病)  
  5.     int msgid = msgget(0x1235,0666|IPC_CREAT|IPC_EXCL);  
  6.     if (msgid < 0)  
  7.     {  
  8.         err_exit("mesget error");  
  9.     }  
  10.     else  
  11.     {  
  12.         cout << "msgid = " << msgid << endl;  
  13.     }  
  14.   
  15.     return 0;  
  16. }  




[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //实践4:低权限创建,高权限打开  
  2. int main()  
  3. {  
  4.     //低权限创建  
  5.     int msgid = msgget(0x255,0444 | IPC_CREAT);  
  6.     if (msgid < 0)  
  7.     {  
  8.         err_exit("mesget error");  
  9.     }  
  10.     else  
  11.     {  
  12.         cout << "Create Mes OK, msgid = " << msgid << endl;  
  13.     }  
  14.   
  15.     //高权限打开  
  16.     msgid = msgget(0x255,0644 | IPC_CREAT);  
  17.     if (msgid < 0)  
  18.     {  
  19.         err_exit("mesget error");  
  20.     }  
  21.     else  
  22.     {  
  23.         cout << "Create Mes OK, msgid = " << msgid << endl;  
  24.     }  
  25.   
  26.     return 0;  
  27. }  


msgget函数参数关系图

 

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐