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. 实例代码
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #include <unistd.h>
- #include <assert.h>
- #include <cstdlib>
- #include <cstring>
- #include <string>
- #include <iostream>
- key_t getKey()
- { // To get the single key under the same user.
- static const int IPCKEY = 0x111;
- char path[256] = {0};
- sprintf( path, "%s/etc/config.ini", (char*)getenv("HOME") );
- return ftok( path, IPCKEY );
- }
- class MyMsg {
- long _type; // This data member mush greate than value "0".
- char _buffer[BUFSIZ];
- public:
- MyMsg():_type(1){}
- inline int type(){return _type;}
- inline char * buffer(){return _buffer;}
- inline void setType(long type = 1){
- assert(type>0);
- if (type > 0) _type = type;
- else _type = 1;
- }
- inline char * setBuffer(const std::string buffer = ""){
- assert( !buffer.empty() );
- memcpy(_buffer,buffer.c_str(),buffer.size()+1);
- }
- };
- int sendMsg(const int msgid)
- {
- MyMsg msg;
- while(true) {
- std::string msgSend;
- std::cin >> msgSend;
- msg.setBuffer(msgSend);
- ssize_t size = msgsnd(msgid, (void *)&msg, msgSend.size()+1, 0);
- std::cout << "msg=" << msg.buffer()
- << ", type=" << msg.type() << std::endl;
-
- if (size == -1) {
- std::cout << "msgsnd failed !\n" << std::flush;
- return -1;
- }
- else {
- std::string strMsg(msg.buffer());
- if (strMsg == "q" || strMsg == "quit" || strMsg == "exit")
- { break; }
- }
- const int type = msg.type();
- if (type > 5) msg.setType(1);
- else msg.setType(1+type);
- }
- return 0;
- }
- int receiveMsg(const int msgid)
- {
- MyMsg msg;
- while(true) {
- ssize_t size = msgrcv(msgid, (void *)&msg, BUFSIZ, 0, 0);
- std::cout << "msg=" << msg.buffer()
- << ", type=" << msg.type() << std::endl;
-
- if (size == -1) {
- std::cout << "msgrcv failed !\n" << std::flush;
- return -1;
- }
- else if (size == 0) {
- std::cout << "msgrcv receive nothing !\n" << std::flush;
- sleep(5);
- std::cout << "5 seconds has past, let's check the message box.\n"
- << std::endl;
- }
- else {
- std::string strMsg(msg.buffer());
- if (strMsg == "q" || strMsg == "quit" || strMsg == "exit")
- { break; }
- }
- }
- return 0;
- }
- int main(int arc, char ** arv)
- {
- if (arc <=1) return -1;
- int msgid = msgget(getKey(), 0666 | IPC_CREAT);
- if (msgid == -1) {
- std::cout << "msgget failed !\n" << std::flush;
- return -1;
- }
-
- std::string command(arv[1]);
- if (command == "send") sendMsg(msgid);
- if (command == "receive") receiveMsg(msgid);
- if (msgctl(msgid, IPC_RMID, 0) == -1) {
- std::cout << "msgctl(IPC_RMID) failed\n" << std::endl;
- return -1;
- }
- return 0;
- }
阅读(522) | 评论(0) | 转发(0) |