先思考:
(1) 进程之间是如何进行通信的;
(2) 缓冲区与缓存区;
(3) 理解内核;
(1) 由于每个进程的空间地址相互独立,因此进程与进程之间是不能相互访问的; 由于进程之间不能相互访问,B进程是看不到A进程的全局变量,那么,要如何才能进行数据交换? 因此交换数据必须通过内核,在内核中开辟一块缓冲区, 进程间通信:A进程将数据从用户空间拷到内核缓冲区,B进程再从内核缓冲区将数据读走; (2) 缓冲区:将数据存在内存中,这个数据在内存空间称为缓冲; 缓存区:从内存中读取数据,这个数据在内存空间称为缓存;
(3)
内核是cpu的核心,内核的权限是很高的,可以直接访问硬件设备和所有内存空间的权限;
那进程是如何从缓冲区把内核数据读取的?
内核有什么功能作用?
后续讲解
进程间的通信方式
进程间的通信(IPC)主要包括:
管道
消息队列
共享内存
信号量
信号
套接字(Socket)
管道
(1)管道传输数据是单向的,如果想相互通则需要创建两个管道,ps auxf | grep mongodb 这个 | 就是一条管道;
(2)管道:
1. 本质是内核里的串缓存;
2. 数据遵循先进先出(FIFO)原则,数据传输是单向的;
3. 在进程间相互通信;
(3)匿名管道:
1. 用 | 表示;
2. 通信范围在父子进程间;<因为匿名管道没有管道文件,只能通过fork来复制父进程,fd描述符,来通信>
3. 生命周期跟进程同生共死;
(4)命名管道:
1. 用mififo创建管道文件<mififo today>;
2. 使用: 创建管道mififo today, 写入管道echo "hello" > today, 读取管道cat < today;
3. 可以在不相关的进程间通信;
(5)缺点:
1. 效率低,频繁的在进程间交换数据,只能单向传输;
2. 容易阻塞,缓冲区有限;
消息队列
消息队列解决了管道在进程间频繁交换数据的问题
(1) 本质:
保存在内核中的消息链表;
(2) 原理:
发送数据会分成一个个独立的数据块,每个数据块都是固定大小,
如果进程从消息队列读取数据块,内核就会把这个数据块删除,
消息队列的生命周期随内核,若未释放消息或未关闭操作系统,消息队列会一直存在,
(3) 工作方式:
A进程将数据块放在对应的消息队列后返回,
B进程需要的时候去读取数据块,
(4)缺点:
通信不及时,
附件大小限制(消息队列不适合大数据传输),
存在用户态与内核间的数据拷贝开销(A进程写入数据到内核中,发生从用户态拷贝数据到内核态的过程,
当B进程去读取内核中的消息数据时,会发生从内核态拷贝数据到用户态的过程)
共享内存
共享内存解决了消息队列用户态与内核态之间的消息拷贝消耗问题;
(1) 共享内存机制: 拿出一块虚拟地址空间,映射到相同的物理内存中;
(2) 每个进程都有自己独立的虚拟空间,对于数据增删改查互不影响;
(3) 缺点:
1. 基于内存,只能在同一个主机间通信;
2. 多进程同时修改一个共享文件,容易造成数据错乱;
信号量
信号量解决了共享内存多进程竞争共享资源的问题,使任意时刻只能被一个进程访问
(1)信号量就是一个整型的计数器,用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据;
(2)信号量表示资源的数量,P操作 -1, V操作 +1, P和V操作必须成对出现在共享资源前后;
(3)信号初始化为1代表互斥信号量,可以保证共享内存在任何时刻只有一个进程在访问;
初始化为0代表同步信号量,可以保证进程A应在进程B之前执行;
信号
(1)对于异常情况下的工作模式,需要用信号的方式通知进程;
(2)信号是进程间通信机制中唯一的异步通信机制,可以在任何时候发送信号给某进程;
(3)用户进程对信号的处理方式:
1.执行默认操作
2.捕捉信号
3.忽略信号
套接字Socket
(1)Socket是进程间通信机制中唯一一个能跨网络与不同主机上进程之间的通信机制;
(2)根据创建Socket类型不同,分为常见的三类通信方式:
·基于TCP协议的通信方式
·基于UDP协议的通信方式
·本地间的通信方式
参考文献: