进程间通信方式(三)-- IPC对象(消息队列、共享内存、信号灯集)

IPC对象

  • 1. IPC对象
  • 2. 查看IPC对象命令
  • 3. 消息队列
    • 3.1 概念
    • 3.2 相关函数
      • 3.2.1 msgget() 创建或者打开消息队列
      • 3.2.2 ftok() 获取键值
      • 3.2.3 msgctl() 控制消息队列
      • 3.2.4 msgsnd() 向消息队列写信息
      • 3.2.5 msgrcv() 从消息队列读
      • 3.3 消息队列 示例
  • 4. 共享内存
    • 4.1 概念
    • 4.2 相关函数
      • 4.2.1 shmget() 创建或者打开一个共享内存
      • 4.2.2 shmctl() 控制共享内存
      • 4.2.3 shmat() 映射共享内存
      • 4.2.4 shmdt() 解除共享内存映射
    • 4.3 共享内存示例
  • 5. 信号灯集
    • 5.1 相关概念
    • 5.2 相关函数
      • 5.2.1 semget() 打开或者创建一个信号灯集
      • 5.2.2 semctl() 控制信号灯集
      • 5.2.3 semop() 执行PV操作
    • 5.3 信号灯集 示例

1. IPC对象

IPC对象主要指三种进程间通信机制:消息队列、共享内存、信号灯集

优点:创建IPC对象后,在当前系统中所有进程都是可见的。


2. 查看IPC对象命令

使用ipcs查看当前ipc对象

ipcs 查看所有的ipc对象
       -q  查看消息队列
       -m 查看共享内存
        -s  查看信号量
ipcrm 删除ipc对象
          ipcrm –q msqid 删除指定的消息队列

3. 消息队列

3.1 概念

  • 消息队列是IPC对象的一种
  • 消息队列由消息队列ID唯一标识
  • 消息队列就是一个消息的列表。用户可以在消息队列中添加消息读取消息等。
  • 消息队列可以按照类型来发送/接收消息

3.2 相关函数

3.2.1 msgget() 创建或者打开消息队列

#include 
#include 
#include 

int msgget(key_t key, int msgflg);
功能:
	创建或者打开一个消息队列,得到消息队列id
参数:
     key:键值,唯一的键值确定唯一的消息队列
         如何设置键值:
             自己直接定义一个键值
             使用ftok函数获取键值
    msgflg:标志位
        一般设置为 IPC_CREAT | 0777
返回值:
    成功:消息队列id
    失败:-1


3.2.2 ftok() 获取键值

#include 
#include 
key_t ftok(const char *pathname, int proj_id);
功能:
	获取键值
参数:
    pathname:路径名
    proj_id:自定义的值,只取前八位
返回值:
    成功:键值
    失败:-1

3.2.3 msgctl() 控制消息队列

#include 
#include 
#include 
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
	控制一个消息队列
参数:
    msqid:消息队列id
    cmd:具体控制
        IPC_STAT 获取消息队列属性信息
        IPC_SET 设置消息队列属性信息
        IPC_RMID 删除一个消息队列
    msqid_ds:消息队列属性结构体
返回值:
    成功:0
    失败:-1

3.2.4 msgsnd() 向消息队列写信息

#include 
#include 
#include 
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向一个消息队列中写入数据
参数:
    msqid:消息队列id
    msgp:要写入的数据,需要自己定义一个结构体
        struct msg_buf{
   
       		 //消息类型,必须有且类型也不能变
      		 // 用于读取数据时,可以指定消息的类型来读取
              long type; 
             //消息正文具体要写入的数据,大小自己定义,类型也可以自定义             
              char mtext[32]; 
        };
    msgsz:消息正文的大小,就是mtext的大小,一定不是第二个参数的大小
    msgflg:标志位
        0   阻塞
        IPC_NOWAIT  非阻塞
返回值:
    成功:0
    失败:-1

3.2.5 msgrcv() 从消息队列读

#include 
#include 
#include 
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, 
                long msgtyp, int msgflg);
功能:从消息队列中读取数据
参数:
    msqid:消息队列id
    msgp:保存读取的数据
    msgsz:消息正文大小
    msgtyp:消息类型
        0    按照顺序读取一个消息
        >0   按照顺序读取第一个消息类型为当前参数的消息
        <0   按照顺序读取第一个消息类型小于等于这个参数的绝对值的类型的消息
    msgflg:标志位
        0   阻塞
        IPC_NOWAIT  非阻塞
返回值:
    成功:接收到的数据的大小
    失败:-1

3.3 消息队列 示例

#include 
#include 
#include 
#include 
#include 
#include 
#include 

typedef struct{
   
    long type;
    int id;
    char name[32];
    int score;
}MSG;

#define DATASIZE (sizeof(MSG) - sizeof(long))

int main(int argc, char const *argv[])
{
   
    //使用ftok函数获取键值
    key_t key;
    if((key = ftok(".", 1000)) == -1)
    {
   
        perror("ftok error");
        exit(1);
    }
    //ftok函数获取的健值就是
    //这个函数的第二个参数的后8位 ↓
    //和 第一个参数对应文件的设备号的后8位 ↓
    //以及这个文件inode号的后16位 ↓
    //共同组成键值
    
    // printf("key = %#x\n", key);
    // struct stat mystat;
    // stat(".", &mystat);
    // printf("dev_num = %x\n", mystat.st_dev);
    // printf("inode = %x\n", mystat.st_ino);
    // printf("1000 = %#x\n", 1000);

你可能感兴趣的:(Linux,C,linux,c语言)