消息队列

系统内核维护了一个存访消息的队列,不同用户可以向队列中发送消息,或者从队列中接收消息。

#include <sys/types.h>

#include sys/ipc.h>

#include <sys/msg.h>

key_t ftok(const char *pathname, int proj_id);

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);

可以用ipcs -q命令查看消息队列信息,用ipcrm -q msqid命令删除消息队列。

两个进程,一个进程创建消息队列,写消息,另一个进程读消息队列中的信息。

流程如下图:

 

代码演示:

msgsnd.c

#include "./common/head.h"

/*功能:
 *创建一个消息队列,并写两条信息。
*/

#define MSGLEN 20
//消息队列结构体,将类型和消息填入该结构体,调用msgsnd函数即可。
typedef struct msgbuf{
    long mtype;            //必须大于0
    char mtext[MSGLEN];    //存放消息队列内容
}MSG;

int main()
{
    key_t key = ftok("./exec.c", 9);    //第一个参数是文件名(任意路径),第二个参数是项目编号,随便传。ftok函数会根据这两个参数,用一个算法生成key值,只要传入的这两个参数是一样的,必定会得到相同的key值。在读取进程中,也是利用这一特性,保证读写操作的是同一个消息队列
    printf("key = %#x\n", key);
    int msgqid = msgget(key, IPC_CREAT | 0666);    //根据key值得到消息队列的id
    printf("msgqid = %d\n", msgqid);

    MSG msg;
    msg.mtype = 1;    //类型
    strncpy(msg.mtext, "online", MGSLEN);    //最多拷贝MSGLEN个字节,不用担心越界
    msgsnd(msgqid, &msg, MSGLEN, 0);    //最后一个参数是权限,默认传0即可。

    msg.mtype = 2;
    strncpy(msg.mtext, "offline", MGSLEN);    
    msgsnd(msgqid, &msg, MSGLEN, 0);      //运行到这里,将两条消息都通过消息队列发送了。等待接收端按照类型接收


    return 0;
}

$ gcc msgsnd.c -o msgsnd

$ ./msgsnd

$ ipcs -q

 可以看到,目前已经有2条消息在消息队列中了。

msgrcv.c

#include "./common/head.h"

/*功能:
 *接收消息队列中的两条消息。
*/

#define MSGLEN 20
//消息队列结构体,调用msgrcv函数即可解析出消息队列的类型和内容
typedef struct msgbuf{
    long mtype;
    char mtext[MSGLEN];
}MSG;

int main()
{
    key_t key = ftok("./exec.c", 9);    //参数必须和发送函数中的一样,才能生成相同的key值
    printf("key = %#x\n", key);
    int msgqid = msgget(key, IPC_CREAT | 0666);
    printf("msgqid = %d\n", msgqid);

    MSG msg;
    msgrcv(msgqid, &msg, MSGLEN, 2, 0);    //第4个参数为消息队列类型,读取类型为2的消息队列
    printf("mtype = %ld\nmtext = %s\n", msg.mtype, msg.mtext);    //将消息队列的类型和消息打印在终端
    msgrcv(msgqid, &msg, MSGLEN, 1, 0);    //读取类型为1的消息队列 
    printf("mtype = %ld\nmtext = %s\n", msg.mtype, msg.mtext);    //打印在终端


    return 0;
}

 $ gcc msgrcv.c -o msgrcv

$ ./msgrcv

$ ipcs -q

可以看到,接收进程正确收到了消息队列中的信息,并按照类型打印出来了。读取过后,消息队列中的消息数变为0。

当读消息队列进程读到没有发送的类型时,会阻塞在这里,等待发送进程发送该类型的信息。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值