2-19 消息队列通信

(本节笔记的实验代码,在这里

1.  基本概念

        消息队列是一个消息链表,每一条消息可看作一个记录,具有一定的格式的结构(struct)。一个进程向队列添加新消息,另一些进程可以从队列中读走消息,消息读走好就消失了。因此消息队列通讯作为IPC(进程间通信)存在。



2.  函数学习

    2.1  创建/打开消息队列

        函数名:

                msgget
        函数原型: man msgget
                int msgget(key_t key, int msgflg);
        函数功能:
                打开或创建消息队列。
        所属头文件:
                <sys/types.h>        <sys/ipc.h>        <sys/msg.h>
        返回值:
                成功 :返回消息队列ID        失败 :返回-1
        参数说明:
                key :消息队列的键值。
                msgflg :打开标志,如果使用了IPC_CREAT,则会新创建一个新的消息队列。


    2.2  发送消息

        函数名:
                msgsnd
        函数原型: man msgsnd
                int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
        函数功能:
                往消息队列里发送消息。
        所属头文件:
                <sys/types.h>        <sys/ipc.h>        <sys/msg.h>
        返回值:
                成功 :返回0        失败 :返回-1
参数说明:
                msqid :要发送到的消息队列的ID。
                msgp :只想要发送的消息,一个结构体指针,该结构体为
                        struct msgbuf{
                                long mtype;    /* 作为该消息的类型,其值>0 */
                                char mtext[1]; /* 该消息的内容 */
                        };
                msgsz :消息内容的大小,特指mtext的size。
                msgflag :标志位。


    2.3  获取消息

        函数名:
                msgrcv
        函数原型: man msgrcv
                ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
        函数功能:
                从消息队列中取出消息。
        所属头文件:
                <sys/types.h>        <sys/ipc.h>        <sys/msg.h>
        返回值:
                成功 :返回实际接收的消息(mtext)数据大小        失败 :返回-1
        参数说明:
                msqid :要接收的消息队列的ID。
                msgp :存放取出消息的指针。
                msgsz :希望取出的消息的最大长度。
                msgtyp :希望取出的消息类型。
                        若type = 0,返回队列的第一个消息;
                        若type > 0,返回消息类型为type的第一个消息;

                        若type < 0,返回队列中消息类型值小于等于type绝对值的消息,

                        如果这种消息有若干个,则取类型值最小的消息。

                msgflag :标志位。


    2.4  删除消息队列
        函数名:
                msgctl
        函数原型: man msgctl
                int msgctl(int msqid, int cmd, struct msqid_ds *buf);
        函数功能:
                控制消息队列。
        所属头文件:
                <sys/types.h>         <sys/ipc.h>         <sys/msg.h>
        返回值:
                成功 :根据的操作返回不同的值         失败 :返回-1
        参数说明
                msqid :要控制的消息队列的id。
                cmd :要执行什么样的控制操作,如IPC_RMID表示删除。
                *buf :获取Linux中描述共享内存的msqid_ds结构,该参数基本不用。


3.  综合实例
/*  touch send.c  */

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <stdlib.h>


#define MSG_SZ 1024
#define MSGKEYP "/arm/key_msq"
#define SHMKEYN "/arm/key_shm"


int *shm;


typedef struct msg_st{
long msg_type;
   char msg_text[MSG_SZ];
}msg_ty;


int main()
{
    int msqid;
   int shmid;
   key_t msg_key;
   key_t shm_key;
    long msgty;
    char msgtx[MSG_SZ];
    msg_ty msg_p;


    /* 1.创建消息队列 */
    msg_key = ftok(MSGKEYP,1);
    shm_key = ftok(SHMKEYN,1);
    msqid = msgget(msg_key,IPC_CREAT);
    shmid = shmget(shm_key, sizeof(int), IPC_CREAT);
    if(-1 == shmid)
    {
        printf("Creat the shm fail!\n");
        exit(EXIT_FAILURE);
    }
    shm = (int *)shmat(shmid, NULL, 0);
    *shm = 0;


    /* 2.循环地从键盘中获得字符串,并把字符串发送到消息队列 */
    while(1)
    {
        printf("Please input the text type, 0 for end!\n");
        scanf("%ld", &msgty);


        if(0 == msgty)
        {
            *shm = 1;
            break;
        }
        printf("Please input the text content:\n");
        scanf("%s", msgtx);


        msg_p.msg_type = msgty;
        strcpy(msg_p.msg_text,msgtx);


        msgsnd(msqid, &msg_p, sizeof(msg_ty), 0);
    }
    
    /* 3.删除消息队列 */
    msgctl(msqid, IPC_RMID, 0);
    shmdt((const void *)shm);
    sleep(10);
    shmctl(shmid, IPC_RMID, 0);
    return 0;
}                                                                  


/*  touch read.c  */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>

#define MSG_SZ 1024
#define MSGKEYP "/arm/key_msq"
#define SHMKEYN "/arm/key_shm"

int msqid;
int shmid;
int *shm;

typedef struct msg_st{
   long msg_type;
   char msg_text[MSG_SZ];
}msg_ty;

void child_process()
{
   msg_ty msg_p;
   while(1)
   {     
       if(1 == *shm)
           exit(0);
        msgrcv(msqid, &msg_p, sizeof(msg_ty), 0, 0);
       printf("The message is: %s\n", msg_p.msg_text);
   }
}

int main()
{

    int i;
    int cpid;
    key_t msg_key;
    key_t shm_key;
    long msgty;
    char msgtx[MSG_SZ];

    /* 1.创建消息队列 */
    msg_key = ftok(MSGKEYP,1);
    shm_key = ftok(SHMKEYN,1);
    msqid = msgget(msg_key,IPC_EXCL);
    shmid = shmget(shm_key, sizeof(int), IPC_CREAT);
    if(-1 == shmid)
    {
        printf("Creat the shm fail!\n");
        exit(EXIT_FAILURE);
    }
    shm = (int *)shmat(shmid, NULL, 0);

    /* 2.创建三个进程,循环地从消息队列取出消息并打印 */
    for(i = 0; i < 3; i++)
    {
        cpid = fork();
        if(cpid < 0)
        {
            printf("Creat child process fail!\n");
        }
        else if(0 == cpid)
            child_process();
    }
    
    return 0;
}                                                                  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值