《精通Unix下C语言编程与项目实践》之八 消息队列发送模型

 
不拘一个遍程序系列程序不能一个脑袋钻到底,有时要学会变通,即所谓的曲线救国。
我的诗歌:都是我的打油诗,但是很值得一读。不要工作还衣食无忧之四难歌   香格里拉美人图
宝宝图片:超可爱的小宝宝 博客
考试培训:主要是关于考研、软考和等级的相关题解。2009考研试题分析   2008年12月程序员试题分析    2009年软考备考全攻略    2008年5月程序员试题解析
《精通Unix下C语言编程与项目实践》之八
消息队列发送模型 
作者:朱云翔,胡平

12.4.2 消息队列发送模型

本处设计一个小例子描述发送消息的实际步骤,本例要求以阻塞方式向消息队列(关键字为KEY)中写入字符串“Hello Unix!”,消息类型为TYPE<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

全部过程共分为5个步骤:

1. 定义消息结构

参照代码12-4,定义以下消息结构:

struct msgbuf

{

    long    mtype;      /* 消息类型 */

    char    ctext[100]; /* 消息数据 */

};

2. 打开(创建)消息队列

int msgid;

msgid = msgget(KEY, 0666|IPC_CREAT);

if (msgid < 0) 打开(创建消息失败)

如果msgid值非负,表示打开(或创建)消息队列成功。

3. 组装消息

设置消息类型和拷贝消息数据:

struct msgbuf buf;                  /* 申请消息缓冲 */

buf.mtype = 100;                    /* 设置消息类型 */

strcpy(buf.ctext, "HELLO Unix!");   /* 拷贝消息数据 */

4. 发送消息

万事俱备,只欠东风,调用函数msgsnd完成消息发送:

int ret;

ret = msgsnd(msgid, &msg, strlen(msg.ctext), 0);

注意,参数msgsz只是消息数据的长度,不包含消息类型长度。

5. 发送判断

在计算机程序设计中,售后处理非常重要,如下所示:

if (ret == -1)

{

    if (errno == EINTR) 信号中断,重新发送;

    else 系统错误

}

进程在发送消息过程中如果接收到信号,将中止消息发送并返回EINTR错误,此时重新发送即可。

实例

本处设计一个消息发送的例子,它循环读取键盘输入,并将输入的字符串信息写入到消息队列(关键字为0x1234)中,如代码12-6所示:

代码12-6 消息发送程序(节自/code/chapter12/msg1.c

#include <sys/msg.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <stdio.h>

#include <sys/errno.h>

extern int errno;

struct mymsgbuf             /* 定义消息结构 */

{

    long    mtype;          /* 消息类型 */

    char    ctext[100];     /* 消息数据 */

};

void main()

{

    struct mymsgbuf buf;    /* 申请消息缓冲 */

    int msgid;

    /* 打开(或创建)消息队列 */

    if ((msgid = msgget(0x1234, 0666|IPC_CREAT)) < 0)

    {

        fprintf(stderr, "open msg %X failed.\n", 0x1234);

        return ;

    }

    while (strncmp(buf.ctext, "exit", 4))

    {

        memset(&buf, 0, sizeof(buf));

        /* 从键盘输入消息数据内容 */

        fgets(buf.ctext, sizeof(buf.ctext), stdin);

        /* 设置消息类型为进程ID */

        buf.mtype = getpid();      

        /* 发送消息 */

        while ((msgsnd(msgid, &buf, strlen(buf.ctext), 0)) < 0)

        {

            if (errno == EINTR) continue;   /* 信号中断,重新发送 */

            return;

        }

    }

}

编译和运行代码12-6    

# make msg1

        cc -O -o msg1 msg1.c

# ./msg1

Please input:Hello World!

Please input:Hello Every Body!

Please input:读者朋友们,你们好!

Please input:exit

函数strncmp对字符串大小进行判断,当两个字符串参数完全相等时返回0,否则返回其它值。

程序调用fgets直接使用消息数据缓冲区存储输入,请确保输入字符串不要超过最大缓冲区限制,即本例中定义的99个字符(最后一个存储ASCII码的“0”)当用户输入exit时程序结束。上例中共发送了4条消息。

执行ipcs命令查询消息发送信息:

# ipcs -a -q

T     ID     KEY        MODE       OWNER    GROUP  CREATOR   CGROUP CBYTES  QNUM QBYTES LSPID LRPID   STIME    RTIME    CTIME

Message Queues:

q    162 0x00001234 --rw-rw-rw-     root      sys     root      sys     57     4  65532  1285     0 12:08:45 no-entry 12:08:28

如上所示,CBYTES值为57QNUM值为4,代表我们成功的写入了4条消息共57个字符信息。请确保执行程序msg1前消息队列0x1234不存在,或队列为空,否则显示的结果将不一致。
 
相关文章:
封面          前言        目录         策划         作者
动态库        变长参数    文件锁       外设         僵死进程
定时器        I/O重定向   消息队列

 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值