系统编程之消息队列

1.创建(获取)消息队列

msgget()

函数声明: int msgget ( key_t key, int msgflg )
返回值: message queue identifier on success失败的话返回-1
第一个参数:可以自己在开头用define宏定义一个任意数字
第二个参数,msgflg 控制的。它可以取下面的几个值:
IPC_CREAT :
如果消息队列对象不存在,则创建之,否则则进行打开操作;
IPC_EXCL:
和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否则产生一个错误并返回。
0:如果已经创建了就填入0;

2.读写消息队列

读:msgrcv()

函数原型: int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long mtype, int msgflg )
返回值: 成功的话返回拷贝入message buffer的字节数(拷贝入msgsz中的字节数)失败的话就是-1
参数
P1-int msqid: 消息队列的控制字(ID),用于区别各个消息队列,通过msgget函数获得,以消息队列的键值作为入参(具体键值可自定义)

P2-struct msgbuf *msgp: 指向消息缓冲区的指针,msgrcv中用于存放接收到的消息,msgsnd中用于存放要发送出的消息
(一般是结构体的地址)

P3-int msgsz: 消息的大小(字节数)

P4-long mtype: 值决定返回哪一条消息(等于0 — 返回队列中最早的一条消息;大于0 — 返回类型为mtype的第一条消息;小于0 — 则返回其类型小于或等于mtype参数的绝对值的最小的一个消息)

P5-int msgflg: 是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数
的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出。

注:函数的前三个参数和msgsnd()函数中对应的参数的含义是相同的。第四个参数mtype指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将之返回。不过这里有一个例外。如果mtype 的值是零的话,函数将不做类型检查而自动返回队列中的最旧的消息。

写: msgsnd()

函数声明: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg )
返回值: 成功返回0,失败返回-1
参数
第一个参数msqid 是消息队列对象的标识符(由msgget()函数得到),第二个参数msgp 指向要发送的消息所在的内存,第三个参数msgsz 是要发送信息的长度(字节数),可以用以下的公式计算:
msgsz = sizeof(struct mymsgbuf) - sizeof(long);
第四个参数是控制函数行为的标志,可以取以下的值:
0,忽略标志位;
IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。

3.销毁消息队列

msgctl()

函数原型:int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
返回值:成功返回0,失败返回-1;
参数
函数的第一个参数 msgqid 是消息队列对象的标识符。
第二个参数 是函数要对消息队列进行的操作,它可以是:
IPC_STAT
取出系统保存的消息队列的msqid_ds 数据,并将其存入参数buf 指向的msqid_ds 结构中。
IPC_SET
设定消息队列的msqid_ds 数据中的msg_perm 成员。设定的值由buf 指向的msqid_ds结构给出。
IPC_RMID
将队列从系统内核中删除。
这三个命令的功能都是明显的,所以就不多解释了。唯一需要强调的是在IPC_STAT命令中队列的msqid_ds 数据中唯一能被设定的只有msg_perm 成员,其是ipc_perm 类型的
数据。而ipc_perm 中能被修改的只有mode,pid 和uid 成员。其他的都是只能由系统来设定
的。
第三个参数可以设置空指针NULL

写(代码)

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#define MSGKEY 1234

struct msgbuf
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1024];    /* message data */
};

int main()
{
    //创建消息队列
    int msgid = msgget(MSGKEY, IPC_CREAT | IPC_EXCL);
    if(-1 == msgid)
    {
        perror("msgget");
        exit(1);
    }
    struct msgbuf m;
    int ret;
    while(1)
    {
        m.mtype = 1; //类型
        scanf("%s",m.mtext);
        ret = msgsnd(msgid,&m,sizeof(m.mtext),0);
        if(-1 == ret)
          {
            perror("msgsnd");
            exit(1);
        }
        if(!strcmp(m.mtext,"bye"))
        {
            break;
        }
        memset(m.mtext,0,sizeof(m.mtext));
    }
    msgctl(msgid, IPC_RMID, NULL); //删除
    return 0;
}

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#define MSGKEY 1234

struct msgbuf
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1024];    /* message data */
};

int main()
{
    //获取消息队列
    int msgid = msgget(MSGKEY,0);
    if(-1 == msgid)
    {
        perror("msgged");
        exit(1);
    }

    struct msgbuf m;
    int ret;
    while(1)
    {
        ret = msgrcv(msgid,&m,sizeof(m.mtext),1,0);
        if(-1 == ret)
        {
            perror("msgrcv");
            exit(1);
        }
        if(!strcmp(m.mtext, "bye"))
        {
            break;
        }
        printf("%s\n", m.mtext);
        memset(m.mtext, 0, sizeof(m.mtext));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值