前面讲述了进程间通信的两种方式 匿名管道 和 命名管道 今天我们继续来看看进程间通信的其他方式system V
system V共享内存
- 共享内存,听名字就知道他是一块内存,这块内存一定是可以被俩个进程同时看到的临界资源,正如我们所想的,这块内存被开辟在物理内存上,然后通过页表映射到各个进程的虚拟地址空间的共享内存段,就像我们下图中所画的那样。
- 共享内存是system V进程间通信速度最快的
共享内存函数
共享内存创建函数 shmget
int shmget(key_t key, size_t size, int shmflg);
- 参数1:共享内存独一无二的编号,由ftok函数构造,下面介绍,这个key就像你的身份证
- 参数2:表示需要开共享内存的大小,单位是页,至少是1页的倍数,也就是4096k的倍数
- 参数3:和open函数的选项类似,这里关键的俩个参数,IPC_CREAT(创建共享内存),IPC_EXCL(与前一个参数配合使用),如果将两个共同使用表示如果共享内存不存在则创建,否则创建失败,IPC_CREAT单独使用不存在则创建,存在则返回已经存在的
获取共享内存key的函数 ftok 函数
key_t ftok(const char *pathname, int proj_id);
有了以上两个函数我就可以试着来创建一个共享内存:
- 我们运行创建共享内存代码,发现第一次运行时无任何现象,然而第二次运行时却出错了
- 通过上述操作我们可以知道,创建共享内存只能创建一次,一旦存在不可重复创建,接下来我们通过
ipcs -m
命令来查看一下我们创建的共享内存
删除共享内存函数 shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- 参数1:传shmget的返回值即可删除
- 参数2:直接传IPC_RMID即可
- 参数3:设置为NULL即可
将共享内存挂接到进程地址空间函数 shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
- 参数1:你所要将进程挂载的共享内存id
- 参数2:设置为NULL即可
- 参数3:设置为0即可
- 返回值:和malloc非常相似,返回了共享内存起始地址的指针
了解了上述函数之后,我们来利用共享内存实现一下进程间的通信
- server.c
- client.c
- 实现两个进程间的通信我们可以看到下图所示情况,client进程在往共享内存中写数据,而server从共享内存中读取数据,此时我们查看共享内存,可以看到我们创建的共享内存中挂载这两个进程
system V消息队列
- 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法
- 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
- 特性方面:IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核
system V信号量
信号量主要用于同步和互斥的,下面先来看看什么是同步和互斥。
进程互斥
- 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥
- 系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源。
- 在进程中涉及到互斥资源的程序段叫临界区
- 特性方面:IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核