进程间通信(IPC)——消息队列

IPC(Inter-Process Communication)进程间通信,提供了各种进程间通信的方法。在Linux C编程中有几种方法
(1) 半双工Unix管道
(2) FIFOs(命名管道)
(3) 消息队列
(4) 信号量
(5) 共享内存
(6) 网络Socket

消息队列

 消息队列是在消息的传输过程中保存消息的容器。消息队列管理器在将消息从它的源中继到它的目标时充当中间人。队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。

 消息队列提供了一个从一个进程向另一个进程发送消息的方法。

消息队列结构体(/usr/include/linux/msg.h)

struct msqid_ds {
    struct ipc_perm msg_perm;
    struct msg *msg_first;      /* first message on queue,unused  */                                                                  
    struct msg *msg_last;       /* last message in queue,unused */
    __kernel_time_t msg_stime;  /* last msgsnd time */
    __kernel_time_t msg_rtime;  /* last msgrcv time */
    __kernel_time_t msg_ctime;  /* last change time */
    unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */
    unsigned long  msg_lqbytes; /* ditto */
    unsigned short msg_cbytes;  /* current number of bytes on queue */
    unsigned short msg_qnum;    /* number of messages in queue */
    unsigned short msg_qbytes;  /* max number of bytes on queue */
    __kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */
    __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
};

消息队列在内核中的表示

消息队列在内核中的表示

系统内核能够创建多少个消息队列?(cat /proc/sys/kernel/msgmni)

每个消息队列能够装多少字节?(cat /proc/sys/kernel/msgmnb)

队列中一条记录最大为多大?(at /proc/sys/kernel/msgmax)

消息队列大小

创建消息队列

int msgget(key_t key, int msgflg);
key: 标识某个消息队列的名字
msgflg: 由九个权限标志构成,它们的⽤用法和创建⽂文件时使⽤用的mode模式标志是一样的
返回值:成功返回消息队列的标识码,失败返回 -1

查看消息队列

ipcs -q
这里写图片描述

往消息队列写数据

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
msgid: 由msgget函数返回的消息队列标识码
msgp:是.一个指针,指针指向准备发送的消息
msgsz:是msgp指向的消息.长度,这个.长度不含保存消息类型的那个long int.长整型
msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
msgflg=IPC_NOWAIT表.示队列满不等待,返回EAGAIN错误。
返回值:
成功返回0;失败返回-1

从消息队列读数据

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数:
msgid: 由msgget函数返回的消息队列标识码
msgp:是⼀一个指针,指针指向准备接收的消息
msgsz:是msgp指向的消息⻓长度,这个⻓长度不含保存消息类型的那个long int⻓长整型
msgtype:它可以实现接收优先级的简单形式
msgflg:控制着队列中没有相应类型的消息可供接收时将要发⽣生的事
返回值:
成功返回实际放到接收缓冲区⾥里去的字符个数,失败返回-1

删除消息队列

命令行手动删除:
ipcrm [ -Q key | -q id ];
在程序中删除消息队列:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数
msqid: 由msgget函数返回的消息队列标识码
cmd:是将要采取的动作,(有三个可取值)
cmd有三个参数:
命令 说明
IPC_STAT 把msqid_ds结构中的数据设置为消息队列的当前关联值
IPC_SET 在进程有足够权限的前提下,把消息队列的当前关联值设置为msqid_ds数据结构中给出的值
IPC_RMID 删除消息队列
返回值:
成功返回0,失败返回-1

消息队列代码示例

struct msgbuf //存放消息的结构体
{
    long channal;
    char buf[1024];
};                                                                                                                                    

int main()
{
    key_t key = ftok(".",'a'); //产生key值
    int msgid = msgget(key,IPC_CREAT); //创建消息队列
    if(msgid==-1)
        perror("msgget"),exit(1);
    struct msgbuf mb;
    fgets(mb.buf,1024,stdin); //写内容到buf中
    int len = strlen(mb.buf);
    if(msgsnd(msgid,&mb,len,0)==-1) //把数据发送到消息队列中
        perror("msgsnd"),exit(1);
    struct msgbuf rcv;
    if(msgrcv(msgid,&rcv,len,0,0)==-1)//从消息队列中读出数据
        perror("msgrcv"),exit(1);
    printf("%s\n",rcv.buf);
    msgctl(msgid,IPC_RMID,0); //删除消息队列
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38646470/article/details/80169406