35-System V 进程间通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35733751/article/details/82853496

1. System V IPC的由来


  Unix 系统早期的IPC形式主要包括无名管道,有名管道,信号,而System V IPC是AT&T实验室对Unix早期的进程间通信手段进行了改进和扩充形成的。

  System V IPC主要包括以下三种进程间通信机制:System V 共享内存、System V 消息队列、System V 信号量,它们都是由 AT&T实验室开发出来的。

   随着不断发展,在1983年,这些IPC被应用于当时主流的System V Unxi系统上(System V是Unix操作系统其中的一个版本),这就是System V IPC名字的由来。


2. 何为System V IPC对象


   System V的每一种IPC机制都被称为IPC对象(共享内存,消息队列,信号量),这些IPC对象存在于内核空间中,标识符是IPC对象在内核空间的内部名,IPC对象可以通过标识符来引用和访问,但是用户空间是无法直接操作内核空间的,为了解决这个问题,每个IPC对象都会有一个键(key)与标识符关联,而这个键(key)就作为IPC对象在用户空间的外部名。

在这里插入图片描述

   如上图所示,以创建共享内存为例,当调用get后缀函数创建内核对象时,其本质就是内核空间分配的一个IPC结构体,也称作IPC内核对象,同时还有一个标识符。然后会将get后缀函数指定的键(key)与标识符(shmid)进行映射,这样用户空间的进程就可以通过标识符(shmid)操作内核空间的共享内存了(当然,这个过程并没有这么简单,因为进程还要把自己的虚拟地址挂接到内核空间,才能操作共享内存)。

   对于共享内存,消息队列,信号量来说,它们在内核空间都有对应的IPC结构体和标识符来描述。


   注意:上图只是为了帮助大家理解键(key)和标识符,IPC对象之间的关系,内核中不一定是这样实现的。


   拿共享内存举例来说,我们通过ipcs命令可以查看共享内存的键(key)和标识符(shmid):
在这里插入图片描述

   图中的键key值就是用户空间所使用的外部名,而标识符shmid就是内核空间所使用的内部名


3. 创建和打开一个System V IPC对象


   我们知道内核空间中的每个 IPC对象(消息队列,信号量,共享内存)都用一个非负整数的标识符来引用,例如:要向一个消息队列发送消息或者从一个消息队列取消息,只需要知道其队列标识符就行了,跟文件描述符相比,IPC标识符不是小的整数,当一个 IPC对象被创建,然后又被删除,这种 IPC对象的标识符会在原先的基础+1(说白了就是只要一创建就会+1),当达到一个最大值时,又会回到0。

   每一种System V IPC对象在创建IPC对象时都需要指定一个键,这个键的数据类型是key_t类型,可以调用相关get后缀函数将这个键(key)和内核标识符(shmid)映射,且这个标识符在内核空间中是唯一的。

   如果指定了一个已经存在的键(key),那么调用相关get后缀函数将会获取到一个IPC对象,换句话说,怎么在创建IPC对象时要保证键(key)的唯一性?关于这个问题一般有三种解决方案:

  1. 随机选取一个整数值作为key值,这些整数放在一个头文件中,所有使用IPC对象的程序都需要包含这个头文件,但这个方案的难点在于可能会使用一个已经被占用的key值。

  2. 在调用相关get后缀函数创建IPC对象时,将IP_PRIVATE常量作为key值,这样每次调用都会创建一个全新的IPC对象,返回一个唯一的标识符(内部名)。

  3. 第三种解决方案是使用ftok函数生成一个(接近唯一的)key值。


   通常,IP_PRIVATE和ftok函数是比较常用的两种解决方案,在下一篇将详细介绍共享内存的IPC对象的创建过程,以及如何使用ftok函数来生成唯一的key值。

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/82853496
今日推荐