美文网首页
进程通信之消息队列

进程通信之消息队列

作者: 二进制人类 | 来源:发表于2022-09-30 11:13 被阅读0次

ftok键值获取

#include <sys/types.h>
#include <sys/ipc.h>
/**
 * [ftok 通过路径和id获取 System V IPC对象机制的唯一标识的键值key,使用于创建IPC对象(消息队列、共享内存、信号灯集)]
 * @param  pathname [表示路径(一般为工程的工作路径)]
 * @param  proj_id  [id(一般位工程id)低8位]
 * @return          [成功返回获取的key值,失败返回-1且修改errno的值]
 */
key_t ftok(const char *pathname, int proj_id);

创建消息队列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/**
 * [msgget 获取消息队列的id]
 * @param  key    [
 * key标识消息的队列的键值
        IPC_PRIVATE: 宏定义,其值位0,当key值使用该宏定义则每次都会创建一个新的消息队列。
        当key为非IPC_PRIVATE,
            如果该key值对应的消息队列已经存在,则获取之前创建好的消息队列的id号。
            如果该key值对应的消息队列不存在,则在msgflg参数中使用IPC_CREAT宏定义创建消息队列,并返回消息的队列的id
 * ]
 * @param  msgflg [
 * msgflg表示获取到的消息队列的权限
        设置消息队列的访问权限,也可设置消息的创建方式:
            IPC_CREAT:创建消息队列;
            IPC_CREAT | IPC_EXCL : 如果要创建的消息队列已经存在,则失败
 * ]
 * @return        [成功返回消息队列的id号,失败返回-1且修改errno的值]
 */
int msgget(key_t key, int msgflg);

IPC对象机制shell命令

ipcs            #查看所有IPC对象
ipcs -q         #查看系统消息队列
ipcs -m         #查看系统共享内存
ipcs -s         #查看系统信号灯集
ipcrm           #删除IPC对象
ipcrm -q 65538  #删除id=65538的消息队列
ipcrm -m 65538  #删除id=65538的共享内存
ipcrm -s 65538  #删除id=65538的信号灯集

消息队列的控制

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/**
 * [msgctl 消息队列的控制]
 * @param  msqid [消息队列id]
 * @param  cmd   [
 * 消息的控制命令
 *  IPC_RMID:删除由msqid指示的消息队列,将它从系统中删除并破坏相关数据结构。
    IPC_STAT:将msqid相关的数据结构中各个元素的当前值存入到由buf指向的结构中。
    IPC_SET:将msqid相关的数据结构中的元素设置为由buf指向的结构中的对应值。
 * ]
 * @param  buf   [msqid_ds数据类型的地址,用来存放或更改消息队列的属性]
 * @return       [成功返回 0 失败返回-1]
 */
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

发送

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/**
 * [msgsnd 向消息队列中添加消息]
 * @param  msqid  [消息队列的id号]
 * @param  msgp   [
 * 所有添加到消息队列中的消息的地址:
    struct msgbuf {
        long mtype;       / message type, must be > 0 /
        char mtext[1];    / message data:此处的大小供参考,需要根据需求定义 /
    };
 * ]
 * @param  msgsz  [消息队列消息正文空间的大小]
 * @param  msgflg [
 * 表示添加消息的方式
        0:阻塞方式发送,msgsnd调用阻塞直到条件满足为止。
        IPC_NOWAIT: 非阻塞方式发送,若消息没有立即发送则调用该函数的进程会立即返回
 * ]
 * @return        [成功返回0,失败返回-1且修改errno的值]
 */
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

实例

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

struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[128];    /* message data:此处的大小供参考,需要根据需求定义 */
};

int main()
{
    key_t key;
    int msgid;
    int ret;
    struct msgbuf mymsgbuf;

    /* 获取IPC对象的键 */
    key = ftok(".", 'm');
    if (key == -1) {
        perror("ftok");
        return -1;
    }

    
    /* 创建消息队列 */
    msgid = msgget(key, IPC_CREAT | 0777);
    if (msgid == -1) {
        perror("msgget");
        return -1;
    }
    
    while(1) {
        /* 设置消息的类型 */
        printf("input msg type: ");
        scanf("%ld", &(mymsgbuf.mtype));
        getchar();
        
        /* 设置消息的正文 */
        printf("input msg text: ");
        fgets(mymsgbuf.mtext, sizeof(mymsgbuf.mtext), stdin);
        
        /* 发送消息 */
        ret = msgsnd(msgid, (const void *)&mymsgbuf, sizeof(mymsgbuf.mtext), 0);
        if (ret == -1) {
            perror("msgsnd");
            return -1;
        }
    }

    /* 删除消息队列 */
    ret = msgctl(msgid, IPC_RMID, NULL);
    if (ret == -1) {
        perror("msgctl->IPC_RMID");
        return -1;
    }
    system("ipcs -q");
}

接收

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/**
 * [msgrcv 接收消息]
 * @param  msqid  [消息队列的id号]
 * @param  msgp   [存放消息结构体的地址]
 * @param  msgsz  [消息正文空间的大小]
 * @param  msgtyp [
 * 表示接收消息的类型
 *  = 0 此时从消息队列中的第一条消息开始依次接收
    > 0 按照类型msgtyp接收,如果在msgflg中使用了宏定义MSG_EXCEPT,则接收不等于msgtyp的消息。
    < 0 读取类型为小于等于-msgtyp的消息
 * ]
 * @param  msgflg [
 * 读取消息的方式
 *  0:msgrcv调用阻塞直到接收消息成功为止。
    MSG_NOERROR:若返回的消息字节数比nbytes字节数多,则消息就会截短到nbytes字节,且不通知消息发送进程。
    IPC_NOWAIT:调用进程会立即返回。若没有收到消息则立即返回-1。返回值:成功返回读取消息的长度,失败返回-1
 * ]
 * @return        [成功返回消息正文字节数,失败返回-1.]
 */
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

实例

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

struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[128];    /* message data:此处的大小供参考,需要根据需求定义 */
};

int main()
{
    key_t key;
    int msgid;
    int ret;
    struct msgbuf mymsgbuf;

    /* 获取IPC对象的键 */
    key = ftok(".", 'm');
    if (key == -1) {
        perror("ftok");
        return -1;
    }

    /* 创建消息队列 */
    msgid = msgget(key, IPC_CREAT | 0777);
    if (msgid == -1) {
        perror("msgget");
        return -1;
    }
    
    while(1) {
        /* 接收消息 */
        ret = msgrcv(msgid, (void *)&mymsgbuf, sizeof(mymsgbuf.mtext), -3, 0);
        if (ret == -1) {
            perror("msgsnd");
            return -1;
        }
        printf("%ld:%s\n", mymsgbuf.mtype, mymsgbuf.mtext);
        sleep(1);
    }

    /* 删除消息队列 */
    ret = msgctl(msgid, IPC_RMID, NULL);
    if (ret == -1) {
        perror("msgctl->IPC_RMID");
        return -1;
    }
    system("ipcs -q");
}

相关文章

  • 进程通信之消息队列

    ftok键值获取 创建消息队列 IPC对象机制shell命令 消息队列的控制 发送 实例 接收 实例

  • 高性能网站实用技巧之消息队列

    什么是消息队列? 消息队列(Message Queue)是一种进程间通信或同一进程的不同线程间的通信方式。进程或者...

  • 高性能网站实用技巧之消息队列篇

    什么是消息队列 消息队列(Message Queue)是一种进程间通信或同一进程的不同线程间的通信方式。进程或者线...

  • 零散的小知识记录(待补充和修改)

    Android跨进程通信:Binder,socket/管道/消息队列,共享内存; linux进程间通信:管道,Bi...

  • 消息队列原理及选型

    什么是消息队列 消息队列(Message Queue)是一种进程间通信或同一进程的不同线程间的通信方式。 什么时候...

  • IPC-消息队列

    消息队列概念 消息队列是IPC(进程间通信,inter process communication)中常用的一种方...

  • PHP进程间通信--消息队列

    前面介绍了怎么通过消息管道(有名消息管道)进行进程间通信,下面介绍如何通过消息队列实现进程间通信。 首先我们来看一...

  • MQ及Kafka

      MQ(Message Queue)消息队列,是一种跨进程的通信方式,应用程序通过写入和检索出入队列的消息来通信...

  • PHP 进程通信-消息队列

    消息队列是消息的链接表(一种常见的数据结构),但是这种消息队列存储于系统内核中(不是用户态),一般我们外部程序使用...

  • Linux进程基础行为(二)

    本节主要讲Linux进程间通信在Linux中,各个进程都共享内核空间,因此LInux进程通信中的管道,消息队列等都...

网友评论

      本文标题:进程通信之消息队列

      本文链接:https://www.haomeiwen.com/subject/zohdartx.html