进程间通信之消息队列msg queue

来源:互联网 发布:java 生成excel 编辑:程序博客网 时间:2024/06/04 23:31

消息message是一个格式化的可变长信息单位。消息机制允许一个进程向任何其他进程发送一个消息。本质上,消息队列很像是内核维护的一个信箱,任何进程都可以向内核发送一封信,这个信包括消息的类型(用long型表示),和消息的内容(char型数组)。任何进程通过IPC对象标识符,就可以向指定的信箱发送消息。类似的,任何进程可以通过IPC对象标识符,来从信箱中收取指定类型的消息。这里的任何进程,是指具有访问权限的任何进程。
下面通过一个例子来了解消息队列。
程序server创建消息队列,其他进程可以通过server进程创建的消息队列来进行通信。这时写消息队列的程序send可以发送消息,任何时候,读消息队列的程序receive可以读取消息。
程序server的源代码msgq.c

#include <sys/types.h>#include <sys/msg.h>#include <unistd.h>#include <stdio.h>int main(){    key_t key;    int msgid;    int retval;    printf("my pid is %d\n", getpid());    key = ftok(".", 'q');    printf("IPC key = 0x%x\n", key);    /* create a message queue with the IPC key */    msgid = msgget(key, IPC_CREAT | 00666);    if(-1 == msgid)    {        perror("msg creat error");        return;    }    else    {        printf("Message Queue msqid=%d\n", msgid);    }    printf("use \"id\", \"ipcs -q [-i msgid]\" to see more details\n");    printf("press Enter to remove the message queue...\n");    getchar();    /* delete the msg queue */    retval = msgctl(msgid, IPC_RMID, NULL);    if(-1 == retval)    {        perror("unlink msg queue error");    }    else    {        printf("msg queue [%d] unlinked OK\n", msgid);    }    return;}

receive.c

#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/msg.h>#include <sys/types.h>#define LEN 512int main(int argc, char *argv[]){    int sflag, ret;    struct msgbuf    {        int mtype;        char mtext[LEN];    }msg_buf;    /*receive message from msg queue */    if(2 != argc)    {        printf("Usage: %s msqID\n", argv[0]);        return;    }    sflag = IPC_NOWAIT | MSG_NOERROR;    do    {        ret = msgrcv(atoi(argv[1]), &msg_buf, sizeof(msg_buf.mtext), 0, sflag);        if(-1 == ret)        {            perror("exit when type=100. msgrcv error");            sleep(1);        }        else        {            printf("pid:%d received [%d] Byte from msqid [%d]\n", \                    getpid(), ret, atoi(argv[1]));            printf("content:[%s]\n", msg_buf.mtext);        }        if(100 == msg_buf.mtype)            break;    }    while(1);    return ;}

send.c

#include <stdio.h>#include <string.h>#include <sys/msg.h>#include <sys/types.h>#define LEN 512int main(int argc, char *argv[]){    int sflag, ret;    struct msgbuf    {        int mtype;        char mtext[LEN];    }msg_buf;    /*send id message*/    if(4 != argc)    {        /*             0  1     2    3 */        printf("Usage: %s msqID type message\n", argv[0]);        return;    }    sflag = IPC_NOWAIT;    msg_buf.mtype = atoi(argv[2]);    strcpy(&msg_buf.mtext[0], argv[3]);    ret = msgsnd(atoi(argv[1]), &msg_buf, strlen(msg_buf.mtext), sflag);    if(-1 == ret)    {        perror("msgsnd error");        return ;    }    else    {        printf("pid:%d sent msg to msqid [%d] OK\n", getpid(), atoi(argv[1]));    }    return ;}

对应的Makefile

SERVER = serverSEND = sRECEIVE = rall:server send receiveserver: msgq.c    gcc msgq.c -o $(SERVER)send: send.c    gcc send.c -o $(SEND)receive: receive.c    gcc receive.c -o $(RECEIVE)clean:    rm -f $(SERVER) $(SEND) $(RECEIVE)

随时的,可以使用命令ipcs -q来查看系统所有的消息队列。
先运行server:

test@test:~$ ./server my pid is 11609IPC key = 0x710400dbMessage Queue msqid=163840use "id", "ipcs -q [-i msgid]" to see more detailspress Enter to remove the message queue...

进程server会建立消息队列后会停止运行,其他进程就可以通过导出的msgq id来进行通信。
然后从另一个终端中运行send,就可以发送消息到id为163840的这个消息队列

test@test:~$ ./s 163840 10 hello

这时通过ipcs -q -i 163840就可以看到163840这个消息队列的很多信息,比如现在消息队列中有多少byte数据,最后一个发送消息的进程进程号是多少。
可以再从第三个终端中运行receive,指定从163840这个消息队列中收取消息。

test@test:~$ ./r 163840pid:11616 received [5] Byte from msqid [163840]content:[hello]exit when type=100. message receive error: No message of desired typeexit when type=100. message receive error: No message of desired typeexit when type=100. message receive error: No message of desired typeexit when type=100. message receive error: No message of desired typeexit when type=100. message receive error: No message of desired typeexit when type=100. message receive error: No message of desired type

r进程收不到类型为100的消息就会循环读取。这时可从第二个终端中查看下消息队列的信息,也可以继续发送其他消息。
当发送类型100的消息时,收消息进程满足退出条件就退出了。
再返回第一个终端中敲下回车,释放申请的IPC资源。

0 0
原创粉丝点击