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

消息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 512

int 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 512

int 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 = server
SEND = s
RECEIVE = r


all:server send receive

server: 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 11609
IPC key = 0x710400db
Message Queue msqid=163840
use "id", "ipcs -q [-i msgid]" to see more details
press 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 163840
pid:11616 received [5] Byte from msqid [163840]
content:[hello]
exit when type=100. message receive error: No message of desired type
exit when type=100. message receive error: No message of desired type
exit when type=100. message receive error: No message of desired type
exit when type=100. message receive error: No message of desired type
exit when type=100. message receive error: No message of desired type
exit when type=100. message receive error: No message of desired type

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yilonglucky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值