5、操作系统——进程间通信(3)(system V-IPC:消息队列)

目录

1、管道的缺点

2、消息队列

3、消息队列的API

  (1)获取消息队列的ID(类似文件的描述符)(msgget)

  (2)发送、接收消息(msgrcv)

    (3)获取和设置消息队列的属性(msgctl)

4、消息队列的使用方法

(1)发送者

(2)接收者

1、管道的缺点

(1)无法读取一个“指定”的数据,因为数据没有标记,故只能按次序挨个读取

(2)多对进程之间的相互通信,要用多对管道分别处理

2、消息队列

(1)有数据标识的特殊管道,每一段被写入的数据都变成带标识的消息。

(2)读取消息的进程只要指定标识就可以正确读取,而不会受到其他消息干扰

(3)从运行效果看,一个带标识的消息队列,就像多条并存的管道

3、消息队列的API

(1)获取消息队列的ID(类似文件的描述符)(msgget)

5、操作系统——进程间通信(3)(system V-IPC:消息队列)_第1张图片

 (2)发送、接收消息(msgrcv)

5、操作系统——进程间通信(3)(system V-IPC:消息队列)_第2张图片

a、发送消息时,消息必须被组织成以下形式

struct msgbuf
{
    long mtype; // 消息的标识
    char mtext[1]; // 消息的正文 可以是任何类型数据
};

发送出去的消息必须以一个 long 型数据打头,作为该消息的标识,后面的数据则没有要求。

b、消息的标识可以是任意长整型数值,但不能是 0L。

c、参数 msgsz 是消息中正文的大小,不包含消息的标识。

(3)获取和设置消息队列的属性(msgctl)

5、操作系统——进程间通信(3)(system V-IPC:消息队列)_第3张图片

4、消息队列的使用方法

(1)发送者

A) 获取消息队列的 ID

B) 将数据放入一个附带有标识的特殊的结构体,发送给消息队列。

#include 
#include 
#include 
#include 

struct msgbuf
{
    long mtype; // 【重点】消息的标识
    int num ; // 消息的正文 可以是任何类型数据
};

int main(int argc, char const *argv[])
{
    
    // 获得KEY值
    key_t key =  ftok("./",  1 );
    printf("key:%d\n" , key );
    
    // 获得消息队列的ID 
    int ID = msgget( key , IPC_CREAT | 0644 );
    printf("消息队列ID 为:%d \n " , ID );

    // 配置消息
    struct msgbuf msg = {
        .mtype = 'X',  // 设置消息数据的类型(标识)
        .num = 1024   // 实际发送的信息
    };

    // 发送消息
    msgsnd(ID , &msg , sizeof(msg.num), MSG_NOERROR);

    // 标记删除
     msgctl(ID , IPC_RMID , NULL );

    return 0;
}

(2)接收者

A) 获取消息队列的 ID

B) 将指定标识的消息读出。

#include 
#include 
#include 
#include 

struct msgbuf
{
    long mtype; // 【重点】消息的标识
    int num ; // 消息的正文 可以是任何类型数据
};

int main(int argc, char const *argv[])
{
    
    // 获得KEY值
    key_t key =  ftok("./",  1 );
    printf("key:%d\n" , key );
    
    // 获得消息队列的ID 
    int ID = msgget( key , IPC_CREAT | 0644 );
    printf("消息队列ID 为:%d \n " , ID );

    // 配置消息
    struct msgbuf msg = {0};

    // 接收消息
    // int  msg  ; 
    int ret_val = msgrcv( ID , &msg, sizeof(msg.num), 'X', MSG_NOERROR );
    printf("ret:%d msg:%d\n" , ret_val, msg.num );


    // 标记删除
    msgctl(ID , IPC_RMID , NULL );
    
    return 0;
}

你可能感兴趣的:(操作系统,开发语言)