长生栈 长生栈
首页
  • 编程语言

    • C语言
    • C++
    • Java
    • Python
  • 数据结构和算法

    • 全排列算法实现
    • 动态规划算法
  • CMake
  • gitlab 安装和配置
  • docker快速搭建wordpress
  • electron+react开发和部署
  • Electron-创建你的应用程序
  • ImgUI编译环境
  • 搭建图集网站
  • 使用PlantUml画时序图
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Living Team

编程技术分享
首页
  • 编程语言

    • C语言
    • C++
    • Java
    • Python
  • 数据结构和算法

    • 全排列算法实现
    • 动态规划算法
  • CMake
  • gitlab 安装和配置
  • docker快速搭建wordpress
  • electron+react开发和部署
  • Electron-创建你的应用程序
  • ImgUI编译环境
  • 搭建图集网站
  • 使用PlantUml画时序图
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 文件操作

  • Linux进程和线程

  • Linux信号

  • 进程间通信

    • 无名管道
    • 有名管道
    • 信号量
    • 共享内存
    • 消息队列
      • 消息队列相关函数
        • msgget函数
        • msgsnd函数
        • msgrcv函数
        • msgctl函数
      • 消息队列举例
        • 接收者代码
        • 发送者代码
  • Socket

  • C语言
  • 进程间通信
DC Wang
2023-03-01
目录

消息队列

# 消息队列

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法,该数据块可以被认为带有一个类型,接收进程可以独立接收不同类型的数据块。 每个数据块都有一个最大长度的限制,系统中所有队列包含的全部数据块的总数也有限制。

# 消息队列相关函数

# msgget函数

该函数用于创建一个新的或打开一个已经存在的消息队列。

#include <sys/tpyes.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int msgget(key_t key, int msgflg);
1
2
3
4
  • key:和其他IPC机制一样,程序必须提供一个键值来命名某个特定的消息队列。
  • msgflg:由权限位组成,可以与IPC_CREAT标识相或
  • 返回值:调用成功返回正整数的队列标识符。失败返回-1。

# msgsnd函数

该函数用来向消息队列中添加一条消息。

  • 消息的长度必须小于系统规定的上限。
  • 消息必须以一个长整型成员变量开始,接收函数将用这个变量来确定消息的类型。
#include <sys/tpyes.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int msgsnd(int msgid, const void* msg_ptr, size_t msg_sz, int msgflg);
1
2
3
4
  • msgid:msgget函数返回的消息队列标识符。
  • msg_ptr:指向准备发送消息的指针,消息以一个长整型成员变量开始。
  • msg_sz:消息的长度,不包括长整型消息类型成员变量的长度。
  • msgflg:控制当消息队列满或队列消息到达系统上限时发生的事情。
    • IPC_NOWAIT:函数立刻返回,不发出消息;否则进程挂起等待消息队列腾出可用空间。

# msgrcv函数

该函数用来从消息队列中读取一条消息。

#include <sys/tpyes.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int msgrcv(int msgid, void* msg_ptr, size_t msg_sz, long int msgtype, int msgflg);
1
2
3
4
  • msgid:msgget函数返回的消息队列标识符。
  • msg_ptr:指向准备接收消息缓冲区的指针,消息以一个长整型成员变量开始。
  • msg_sz:消息的长度,不包括长整型消息类型成员变量的长度。
  • msg_type:接收优先级。如果值为0,即取出消息队列中的第一个消息;如果为正数,将取出具有相同消息类型的消息;如为负数,将取出消息类型小于或等于msg_type绝对值的第一个消息。
  • msgflg:控制当当前消息队列中没有相应类型消息可以接收时发生的事情。IPC_NOWAIT:函数立刻返回,返回值为-1;否则进程挂起以等待一条对应消息的到来。
  • 返回值:成功时函数返回放到接收缓冲区中的字节数,消息被拷贝到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息,失败返回-1.

# msgctl函数

该函数作用与共享内存的控制函数 (opens new window)很相似。

#include <sys/tpyes.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int msgctl(int msgid, int command, struct msgid_ds* buf);
1
2
3
4
  • 成功返回0,失败返回-1。
  • 如果删除消息队列时,一个进程正在msgsnd或msgrcv函数中等待,则这两个函数将失败。

# 消息队列举例

编写两个程序,receive.c用于接收消息,send.c用于发送消息。

允许两个程序创建消息队列,但只有接收者在接收完最后一个消息之后可以删除它。

# 接收者代码

// receive.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msg_st
{
    long int my_msg_type;
    char some_text[BUFSIZ];
};

int main()
{
    int running = 1;
    int msgid;
    struct my_msg_st some_data;
    long int msg_to_receive = 0;
    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
    if (msgid == -1)
    {
        fprintf(stderr, "msgget failed with error: %d\n", errno);
        exit(EXIT_FAILURE);
    }
    while(running)
    {
        if (msgrcv(msgid, (void *)&some_data, BUFSIZ,
            msg_to_receive, 0) == -1)
        {
            fprintf(stderr, "msgrcv failed with error: %d\n", errno);
            exit(EXIT_FAILURE);
        }
        printf("You wrote: %s", some_data.some_text);
        if (strncmp(some_data.some_text, "end", 3) == 0)
        {
            running = 0;
        }
    }
    if (msgctl(msgid, IPC_RMID, 0) == -1)
    {
        fprintf(stderr, "msgctl(IPC_RMID) failed\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 发送者代码

// send.c

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

#define MAX_TEXT 512

struct my_msg_st
{
    long int my_msg_type;
    char some_text[MAX_TEXT];
};
int main()
{
    int running = 1;
    struct my_msg_st some_data;
    int msgid;
    char buffer[BUFSIZ];

    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

    if (msgid == -1)
    {
        fprintf(stderr, "msgget failed with error: %d\n", errno);
        exit(EXIT_FAILURE);
    }

    while(running)
    {
        printf("Enter some text: ");
        fgets(buffer, BUFSIZ, stdin);
        some_data.my_msg_type = 1;
        strcpy(some_data.some_text, buffer);

        if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1)
        {
            fprintf(stderr, "msgsnd failed\n");
            exit(EXIT_FAILURE);
        }
        if (strncmp(buffer, "end", 3) == 0)
        {
            running = 0;
        }
    }

    exit(EXIT_SUCCESS);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
编辑 (opens new window)
#Linux#进程间通信#IPC
上次更新: 2023/03/31, 22:34:04
共享内存
C linux socket tcp封装库

← 共享内存 C linux socket tcp封装库→

最近更新
01
ESP32-网络摄像头方案
06-14
02
ESP32-PWM驱动SG90舵机
06-14
03
ESP32-实时操作系统freertos
06-14
更多文章>
Theme by Vdoing | Copyright © 2019-2025 DC Wang All right reserved | 辽公网安备 21021102001125号 | 吉ICP备20001966号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式