目录
进程间通信背景
1、为什么要通信?
2、通信的中介是共享资源,而不是某一个进程创建的。

3、进程间通信的分类(3类)




管道
什么是管道?
• 管道是Unix中最古⽼的进程间通信的形式。
• 我们把从⼀个进程连接到另⼀个进程的⼀个数据流称为⼀个"管道"

匿名管道(父子通信)
父子进程通过指向同一个struct file的缓冲区进行通信,如下图所示:

1、条件:父子看到同一份内存空间
2、真正的通信:是内存级的,也就是不用写回磁盘,是内存级别的数据交换
3、管道:父进程读,子进程写,单项通信
4、这个打开的文件是内存级别的,没有路径,也没有文件名,所以是匿名管道

5、匿名管道的特性:
父子进程具有同步机制:①子进程写了,父进程才能读。②子进程把管道写满了,必须等父进程读完,子进程才能再写。
面向字节流:读不取决于写,有可能只能读一个字节,也有可能每次读10个字节,是可以规定的,不由写去规定。
文件的生命周期是随进程的:进程消失,文件也消失

6、基于匿名管道------进程池
父进程多次创建多个子进程,就是 进程池。
先有子进程,再有任务。当有任务直接交给子进程,不用再创建子进程,这就叫做池化技术。池化技术减少创建某种资源的成本,提高别人访问这个的效率。

当父进程把任务只交给一个子进程时,会导致负载不均衡;所以要用某种方法使得任务被多个子进程都可以做,那就是负载均衡。
命名管道(没有血缘关系)
1、两个不相干的进程看到同一份资源;
2、mkfifo(文件名,权限)创建管道文件

3、命名管道的特性:必须有两个进程打开。eg.write方没有执行open的时候,read方,就要在open内部进行阻塞,直到有人把管道文件打开了,open才会返回!
4、假设client是写端,server是读端,server创建命名管道和client通信。把写端关闭后,也就是client关闭后,对应的server读的话收到的返回值是0

SystemV共享内存
1、是一种进程间通信的标准,Linux内核支持了这种标准,通信的模块


A和B拿到同一份key,通过tok去创建。
用户需要给操作系统传一个key,来找到唯一的共享内存;
shmget会给用户返回一个共享内存的标识,使得用户拿着这个标识去访问操作共享内存;注意共享内存也是文件,在shmget的时候注意要设置共享内存的权限0666,不然共享内存不能关联成功

2、共享内存不随进程结束而结束,随内核,需要手动去删除

shmat(at=attach关联)接口,就是把物理内存地址和虚拟地址进行映射/挂接/关联,类似于我们之前学过的malloc,只是shmat是在堆栈之间开辟空间,而malloc是在堆上开辟空间,都是返回虚拟地址的空间

3、读写共享内存没有用到系统调用的read()和write(),但是管道通信用到了系统调用,这是因为对于共享内存来说,这段空间是堆栈之间的,是用户可以访问的,而管道的内存空间是只能由操作系统访问的,用户不能访问


4、共享内存没有保护机制,会出现数据不一致的问题,A还没写完,B就读了,所以共享内存也更快

5、如果非要保护的话,用什么保护呢?命名管道!
A和B之间建立命名管道,当A写完完整数据之后,在管道内通知B可以在共享内存中读取了,然后B再取数据,就实现了A与B的同步机制。
6、共享内存的大小必须是4096的整数倍

7、描述共享内存的结构体

SystemV消息队列
1、通信机制:
在OS内部维护一个队列,A可以放数据,B也可以放数据,但是取的时候怎么知道这个数据是对方的数据而不是自己的数据,通过传递消息类型,也就是做标记





SystemV信号量
1、临界资源:被保护起来的那一部分内存称为临界资源
2、临界区:Client和Server都会有各自的代码,其中某一部分代码都会访问临界资源,那这一部分代码就叫做临界区,其他剩余的不访问临界资源的代码就叫做非临界区。
3、保护的方式:互斥与同步
互斥:给临界区加锁,同一时间只能允许一个进程访问临界区
同步:所有进程都按照顺序访问临界区,都不会插队
4、系统中某些资源⼀次只允许⼀个进程使⽤,称这样的资源为临界资源或互斥资源。 •
5、在进程中涉及到互斥资源的程序段叫临界区。你写的代码=访问临界资源的代码(临界区)+不访问 临界资源的代码(⾮临界区)
6、所谓的对共享资源进⾏保护,本质是对访问共享资源的代码进⾏保护。

7、信号量的本质:临界资源的计数器

8、信号量怎么实现通信,通信不一定非要是数据信息,也可以是控制信息的传递,通过一个进程退出,释放资源,下一个进程就可以进来使用这份资源,这不就是这个进程变向的控制另外一个进程吗?也就是实现了通信的效果。

内核组织管理IPC资源

