Chinaunix首页 | 论坛 | 博客
  • 博客访问: 346999
  • 博文数量: 88
  • 博客积分: 1695
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-06 15:48
个人简介

喜欢美食, 旅行..

文章分类

全部博文(88)

文章存档

2014年(2)

2013年(12)

2012年(14)

2010年(8)

2009年(52)

我的朋友

分类: LINUX

2012-12-09 19:02:14

1. 相关API介绍
key_t ftok( char * fname, int id ) // fname就时你指定的文件名,id是子序号。
系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。  
在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。查询文件索引节点号的方法是: ls -i 
当删除重建文件后,索引节点号由操作系统根据当时文件系统的使用情况分配,因此与原来不同,所以得到的索引节点号也不同。
如果要确保key_t值不变,要目确保ftok的文件不被删除,要么不用ftok,指定一个固定的key_t值。

int msgget(key_t key, int msgflg); //创建消息队列。
  key:消息队列关联的键
  msgflg:消息队列的建立标志和存取权限 

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
  msqid:消息队列的识别码。
  msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下
  struct msgbuf {
  long mtype; /* 消息类型,必须 > 0 */
  char mtext[1]; /* 消息文本 */
  };
  msgsz:消息的大小。
  msgtyp:消息类型
  msgtyp等于0 则返回队列的最早的一个消息。
  msgtyp大于0,则返回其类型为mtype的第一个消息。
  msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。
  msgflg: 用来指明核心程序在队列没有数据的情况下所应采取的行动。如果msgflg和常数IPC_NOWAIT合用,则在msgsnd()执行时若是消息队列已 满,则msgsnd()将不会阻塞,而会立即返回-1,如果执行的是msgrcv(),则在消息队列呈空时,不做等待马上返回-1,并设定错误码为 ENOMSG。当msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取阻塞等待的处理模式。

int msgctl ( int msgqid, int cmd, struct msqid_ds *buf ); // 控制对消息队列的操作
  cmd等于IPC_STAT :读取消息队列的数据结构msqid_ds,并将其存储在b u f指定的地址中。
  cmd等于IPC_SET  :设置消息队列的数据结构msqid_ds中的ipc_perm元素的值。这个值取自buf参数。
  cmd等于IPC_RMID :从系统内核中移走消息队列。

2. 实例代码

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/msg.h>
  4. #include <unistd.h>
  5. #include <assert.h>
  6. #include <cstdlib>
  7. #include <cstring>
  8. #include <string>
  9. #include <iostream>

  10. key_t getKey()
  11. { // To get the single key under the same user.
  12.     static const int IPCKEY = 0x111;
  13.     char path[256] = {0};
  14.     sprintf( path, "%s/etc/config.ini", (char*)getenv("HOME") );
  15.     return ftok( path, IPCKEY );
  16. }

  17. class MyMsg {
  18.     long _type; // This data member mush greate than value "0".
  19.     char _buffer[BUFSIZ];
  20. public:
  21.     MyMsg():_type(1){}
  22.     inline int type(){return _type;}
  23.     inline char * buffer(){return _buffer;}
  24.     inline void setType(long type = 1){
  25.         assert(type>0);
  26.         if (type > 0) _type = type;
  27.         else _type = 1;
  28.     }
  29.     inline char * setBuffer(const std::string buffer = ""){
  30.         assert( !buffer.empty() );
  31.         memcpy(_buffer,buffer.c_str(),buffer.size()+1);
  32.     }
  33. };

  34. int sendMsg(const int msgid)
  35. {
  36.     MyMsg msg;
  37.     while(true) {
  38.         std::string msgSend;
  39.         std::cin >> msgSend;
  40.         msg.setBuffer(msgSend);
  41.         ssize_t size = msgsnd(msgid, (void *)&msg, msgSend.size()+1, 0);
  42.         std::cout << "msg=" << msg.buffer()
  43.                 << ", type=" << msg.type() << std::endl;
  44.         
  45.         if (size == -1) {
  46.             std::cout << "msgsnd failed !\n" << std::flush;
  47.             return -1;
  48.         }
  49.         else {
  50.             std::string strMsg(msg.buffer());
  51.             if (strMsg == "q" || strMsg == "quit" || strMsg == "exit")
  52.             { break; }
  53.         }

  54.         const int type = msg.type();
  55.         if (type > 5) msg.setType(1);
  56.         else msg.setType(1+type);
  57.     }
  58.     return 0;
  59. }

  60. int receiveMsg(const int msgid)
  61. {
  62.     MyMsg msg;
  63.     while(true) {
  64.         ssize_t size = msgrcv(msgid, (void *)&msg, BUFSIZ, 0, 0);
  65.         std::cout << "msg=" << msg.buffer()
  66.                 << ", type=" << msg.type() << std::endl;
  67.         
  68.         if (size == -1) {
  69.             std::cout << "msgrcv failed !\n" << std::flush;
  70.             return -1;
  71.         }
  72.         else if (size == 0) {
  73.             std::cout << "msgrcv receive nothing !\n" << std::flush;
  74.             sleep(5);
  75.             std::cout << "5 seconds has past, let's check the message box.\n"
  76.                       << std::endl;
  77.         }
  78.         else {
  79.             std::string strMsg(msg.buffer());
  80.             if (strMsg == "q" || strMsg == "quit" || strMsg == "exit")
  81.             { break; }
  82.         }
  83.     }
  84.     return 0;
  85. }

  86. int main(int arc, char ** arv)
  87. {
  88.     if (arc <=1) return -1;

  89.     int msgid = msgget(getKey(), 0666 | IPC_CREAT);
  90.     if (msgid == -1) {
  91.         std::cout << "msgget failed !\n" << std::flush;
  92.         return -1;
  93.     }
  94.     
  95.     std::string command(arv[1]);
  96.     if (command == "send") sendMsg(msgid);
  97.     if (command == "receive") receiveMsg(msgid);

  98.     if (msgctl(msgid, IPC_RMID, 0) == -1) {
  99.         std::cout << "msgctl(IPC_RMID) failed\n" << std::endl;
  100.         return -1;
  101.     }
  102.     return 0;
  103. }

阅读(522) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~