IPC之消息队列

来源:互联网 发布:udp监听端口 编辑:程序博客网 时间:2024/05/16 07:26

key_t键和ftok()函数

* 消息队列、信号量和共享内存具有内核持续性(与具体进程周期不相关),故需要在内核用一个全局唯一的Key来标识。

* 这个Key的类型为整数key_t (#include<sys/types.h>),可以在代码写死,也可以用ftok()函数生成
* key_t ftok( const char * fname, int id )
- fname为已存在的文件(不存在返回-1),id为子序号。通过fname文件索引节点号加上子序号构造Key

- 使用例子:

#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>int main(){    const char *pMsgPath = "/data/home/andyawang/code/ipc/MsgQueue";    key_t key = ftok(pMsgPath, 1);    printf("Key : %d\n", key);    return 0;}

2个命令:ipcs和ipcrm
* ipcs用于显示当前内核这3种IPC的各种信息,ipcrm为删除
* 使用例子:

# ipcs------ Shared Memory Segments --------key        shmid      owner      perms      bytes      nattch     status      0x00000000 0          root       666        12000      6          dest         0x00005fe7 32769      root       666        524288     2                       0x00005fe8 65538      root       666        2097152    12  ------ Semaphore Arrays --------key        semid      owner      perms      nsems     0x00008708 32769      root       666        1         0x000086f8 589826     root       666        1------ Message Queues --------key        msqid      owner      perms      used-bytes   messages    0x5ca04f5b 3473408    root 666        0            0         


消息队列
* 内核维护的一个以消息为单位的队列,实质为一个链表结构


数据结构msqid_ds (#include<sys/msg.h>)

struct msqid_ds{    struct msqid_ds {    struct ipc_perm msg_perm;    struct msg *msg_first;      /* first message on queue,unused  */    struct msg *msg_last;       /* last message in queue,unused */    __kernel_time_t msg_stime;  /* last msgsnd time */    __kernel_time_t msg_rtime;  /* last msgrcv time */    __kernel_time_t msg_ctime;  /* last change time */    unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */    unsigned long  msg_lqbytes; /* ditto */    unsigned short msg_cbytes;  /* current number of bytes on queue */    unsigned short msg_qnum;    /* number of messages in queue */    unsigned short msg_qbytes;  /* max number of bytes on queue */    __kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */    __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */};


* 相关函数

#include <sys/ipc.h>#include <sys/msg.h>// 创建或打开一个消息队列int msgget(key_t key, int 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);// 控制操作,如删除等int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );


* 使用例子:

[服务端:MsgQueSvr,cpp,循环 { 接收消息类型为1的消息之后,就发送消息类型为2的消息 } ]

#include <iostream>#include <string.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>using namespace std;const int MAXSIZE = 100;// 消息的数据结构:// * 最前必须有一个long来作为消息的类型,剩下的可自定义struct SMsgUnit{    long type;    int len;    char data[MAXSIZE];};int main(){    struct SMsgUnit sMsg;    key_t iKey;    int iMsgId;    // Get MsgQue Key    const char *pMsgPath = "/data/home/andyawang/code/ipc/MsgQueue";    if ((iKey = ftok(pMsgPath, 1)) == -1) {        cout << "Ftok Err" << endl;        return -1;    }    // 1.msgget    if ((iMsgId = msgget(iKey, IPC_CREAT|IPC_EXCL|0666)) == -1) {        cout << "Msgget Err" << endl;        return -1;    }    // 2.msgrcv & msgsnd    for(int i = 0; i < 5; i ++)    {        msgrcv(iMsgId, &sMsg, sizeof(struct SMsgUnit), 1, 0);        cout << "Svr Recv Msg, type=" << sMsg.type << ", len=" << sMsg.len << ", data=" << sMsg.data << endl;        sMsg.type = 2;        strcpy(sMsg.data, "I Am Svr..");        sMsg.len = strlen(sMsg.data);        msgsnd(iMsgId, &sMsg, sizeof(struct SMsgUnit), 0);    }    // 3.msgctl    if (msgctl(iMsgId, IPC_RMID, NULL) == -1) {        cout << "Msgctl Err" << endl;        return -1;    }    return 0;}
[客户端:MsgQueCli.cpp,发送消息类型为1的消息之后,就接收消息类型为2的消息 ]

#include <iostream>#include <string.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>using namespace std;const int MAXSIZE = 100;struct SMsgUnit{    long type;    int len;    char data[MAXSIZE];};int main(){    struct SMsgUnit sMsg;    key_t iKey;    int iMsgId;    // Get MsgQue Key    const char *pMsgPath = "/data/home/andyawang/code/ipc/MsgQueue";    if ((iKey = ftok(pMsgPath, 1)) == -1) {        cout << "Ftok Err" << endl;        return -1;    }    // 1.msgget    if ((iMsgId = msgget(iKey, IPC_CREAT|0666)) == -1) {        cout << "Msgget Err" << endl;        return -1;    }    // 2.msgsnd    sMsg.type = 1;    strcpy(sMsg.data, "I Am Cli..");    sMsg.len = strlen(sMsg.data);    msgsnd(iMsgId, &sMsg, sizeof(struct SMsgUnit), 0);    // 3.msgrcv    msgrcv(iMsgId, &sMsg, sizeof(struct SMsgUnit), 2, 0);    cout << "Cli Recv Msg, type=" << sMsg.type << ", len=" << sMsg.len << ", data=" << sMsg.data << endl;    return 0;}




1 0