Linux 进程间通信(system v 消息队列, 阻塞式)实

消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点。作为早期unix通信机制之一的信号能够传送的信息量有限,后来虽然POSIX 1003.1b在信号的实时性方面作了拓广,使得信号在传递信息量方面有了相当程度的改进,但是信号这种通信方式更像"即时"的通信方式,它要求接受信号的进程在某个时间范围内对信号做出反应,因此该信号最多在接受信号进程的生命周期内才有意义,信号所传递的信息是接近于随进程持续的概念(process-persistent);管道及有名管道及有名管道则是典型的随进程持续IPC,并且,只能传送无格式的字节流无疑会给应用程序开发带来不便,另外,它的缓冲区大小也受到限制。

/*
 *
 *       Filename:  producer.c
 *
 *    Description:  生产者进程
 *
 *        Version:  1.0
 *        Created:  09/30/2011 04:52:23 PM
 *       Revision:  none
 *       Compiler:  gcc(g++)
 *
 *         Author:  |Zhenghe Zhang|, |zhenghe.zhang@gmail.com|
 *        Company:  |Shenzhen XXX Technology Co., Ltd.|
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <error.h>

#define BUFFER      10 //定义buf大小

struct msgtype {
    long mtype;
    char buf1[BUFFER + 1];
    char buf2[BUFFER + 1];
    long size;
};

int main()
{
    key_t msgkey;

/*消息队列*/
    int msgid;
    struct msgtype msg;

msgkey = ftok("/home/zhang/shmipcx", 10001);
    if(msgkey == -1)
    {
        perror("ftok");
        exit(1);
    }

/*得到消息队列标识符或创建一个消息队列对象并返回消息队列标识符*/
    msgid = msgget(msgkey, IPC_CREAT | 0666);
    if(msgid == -1)
    {
        perror("msgget");
        exit(1);
    }

int i = 0;
    while(i < 10)
    {
        memset(msg.buf1, 0, BUFFER + 1);
        memset(msg.buf2, 0, BUFFER + 1);

sprintf(msg.buf1, "buf1_0x%x", i);      
        sprintf(msg.buf2, "buf2_0x%x", i + 'a');
      
        msg.mtype = 1001;
        msg.size  = i;

printf("msg.mtype = %ld, msg.size = %ld\t", msg.mtype, msg.size);
        printf("msg.buf1 = %s, msg.buf2 = %s\n", msg.buf1, msg.buf2);

/*将msgp消息写入到标识符为msqid的消息队列*/
        /*msgsz, 要发送消息的大小,不含消息类型占用的4个字节,即mtext的长度*/
        /*msgflg 0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列*/
        /*msgflg IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回*/
        /*msgflg IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。*/       
        if(msgsnd(msgid, &msg, sizeof(struct msgtype) - sizeof(long), 0) == -1)
        {
            perror("msgsnd");
            exit(1);
        }

i++;
        sleep(1);  
    }

sleep(30); //等待消费者进程退出

/*获取和设置消息队列的属性*/
    /*cmd IPC_STAT:获得msgid的消息队列头数据到buf中*/
    /*cmd IPC_RMID:删除消息队列*/
    if(msgctl(msgid, IPC_RMID, 0) == -1)
    {
        perror("msgctl");
        exit(1);
    }

return 0;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/23340.html