目录

Linux-进程间通信

Linux 进程间通信


1. 目的

· 数据传输 :一个进程需要将它的数据发送给另一个进程

· 资源共享 :多个进程之间共享同样的资源

· 事件通知 :一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时通知父进程)

· 进程控制: 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

本质:让不同的进程,看到同一份资源!

2. 管道

2.1 核心原理

https://i-blog.csdnimg.cn/direct/40b6dc2787db44d584aeadd9250b7520.png

所以,内核文件系统的设计管理本身就可以做到:让不同的进程,看到同一份资源。

我们把从一个进程连接到另一个进程的一个 数据流 称为一个 “管道”。

2.2 匿名管道

使用系统接口,基于内核创建管理的一种 “ 内核级文件 ” ,本质是一个 内核缓冲区 ,进程通过读写这个缓冲区实现通信。

#include <unistd.h>

       int pipe(int pipefd[2]);

输出型参数:pipefd文件描述符数组: pipefd[0]读端pipefd[1]写端

成功返回0; 失败返回-1, 错误码被设置

只能 用于具有 “亲缘关系” 的进程之间, 通常用于父子进程 ,因为子进程继承拷贝了父进程的大部分内核数据结构信息,这其中就 包括所打开的文件信息(fd_arry)。

四种情况:(命名管道也一样)

1. 管道内没有数据 && 写端不关闭:读端阻塞等待

2. 管道内被写满 && 读端不关闭 : 写端阻塞等待

3. 写端关闭,读端可以继续读取管道内的数据,直到读完

4. 读端关闭 && 写端尝试写入,OS发送异常信号(13)直接终止写端进程

五种特性:

1. 用于具有亲缘关系的进程间

2. 单向性 (命名管道同)

3. 面向字节流(命名管道同)

4. 自带同步机制(即上述的 “四种情况”)(命名管道同)

5. 生命周期随进程,临时性

补充: 默认管道大小通常是64KB,系统全局最大管道大小可以通过 /proc/sys/pipe-max-size 进行调整;也可以在创建管道后,使用 fcntl 系统调用动态调整管道的大小。

为什么要有大小限制?

首先是 为了 避免资源耗尽 ,若不限制管道的大小,多个进程可能消耗大量内存,导致系统不稳定 。

其次是 为了 平衡速度与内存 :适当的管道大小可以在速度和内存占用之间找到平衡。

所以,设置合适的管道大小,有助于提高进程间的通信效率,避免不必要的阻塞。

2.3 命名管道

磁盘级文件,但是不能持久化存储数据。

它可以 让没有 “亲缘关系” 的进程间也能通信

创建:

  1. 系统的指令工具:mkfifo

  2. C 库函数:

#include <sys/types.h>
#include <sys/stat.h>

       int mkfifo(const char *pathname, mode_t mode);

成功返回0; 失败返回-1, 错误码被设置。

在操作上,和 匿名管道不同的是: 命名管道的打开规则(open)

通常,如果不设置 O_NONBLOCK 参数:

写端先启动,阻塞等待 直到有写端打开时才同步打开此管道

读端先启动 , 读端进程阻塞,等待写端进程打开管道;此时启动写端进程,由于读端已经阻塞,导致写端进程也卡住,等待读端准备好读取数据 —— 这是典型的 死锁 情况:读写端互相等待,导致两个进程都 无法继续执行

解决方式:1. 写端先open

  1. 设置非阻塞参数: O_NONBLOCK

  2. 设置管道超时机制

……

3. System V IPC

3.1 简介

用于在不同进程之间交换数据 或 同步 的机制!

同步异步 是计算机科学和编程中的常见概念,主要用于描述 任务执行的方式 以及 程序流控制

同步(Synchronous) : 【阻塞式执行】 任务按照顺序执行,一个任务必须等待前一个任务完成后才能继续,确保多个进程访问共享资源 的 原子性操作【某个操作,只有两种状态,要么还没开始,要么已经结束】 , 防止资源竞争和数据冲突

异步(Asynchronous): 任务可以 并行或非阻塞执行 ,不需要等待前一个任务完成; 提高效率,减少等待时间 ,但是代码 复杂度增加,难以调试和控制程序流 。

场景:

同步:文件读写,小型脚本,CLI命令,…

异步:网络请求,GUI事件处理,服务器处理多用户请求,…

在实际开发中,同步和异步通常结合使用,根据具体的场景才能选择合适的方案。

回到正题:

System V IPC 是一套独立于文件系统的通信机制,通过 内核维护IPC对象资源 在进程间进行通信,所以, 即使进程终止,IPC对象仍然可以保留在内核中,直到显示删除 ;它在一定程度上,避免了传统文件系统操作带来的性能开销,适合高效的进程间数据交换和同步。

它包括:共享内存,消息队列,信号量

接下来,以共享内存为重点讲解,其它次之来分别介绍

3.2 共享内存(Shared  Memory)

基于内存段,直接映射到进程的地址空间,数据在内存中传递(双向,可读可写),减少了内核态与用户态切换以及数据拷贝,速度快,传输量大

操作:

1. 创建/获取 https://i-blog.csdnimg.cn/direct/378d766b17454761a24719be1f91ff0b.png

2. 映射到进程的地址空间/解除映射

https://i-blog.csdnimg.cn/direct/375cf7af3d0b4470889a39da9e63c49c.png

3. 控制

https://i-blog.csdnimg.cn/direct/6c8423636eee498782283c4bbd33e9fd.png

3.3 消息队列 (Message Queues)

允许一个进程以 结构化 消息的形式向队列发送消息,另一个进程向队列中读取消息;消息有优先级,可以按照特定顺序读取

操作是类似的( 注意对比 ):

https://i-blog.csdnimg.cn/direct/8f15083939e04cdd845ad527efc88fa6.png https://i-blog.csdnimg.cn/direct/ad913e6a488248df8bddd2b73becd2a2.png

3.4 信号量(Semaphores)

主要用于进程间的 同步【具有一定的顺序性】 和 互斥 【对共享资源的独占访问】 ,确保进程在访问共享资源时的协调和安全性;并不作为一种朴素的数据通信。

我们把 共享资源 就称为 : 临界资源 或 互斥资源

涉及到访问临界资源的程序代码就叫: 临界区

信号量的本质就是:一个描述管理互斥资源的 “计数器”

下面引入一个具体的场景进行类比理解: https://i-blog.csdnimg.cn/direct/f68e4acc18ba44eaa5a22b3009c36540.png

用户态接口: https://i-blog.csdnimg.cn/direct/100315838b7e40798a21b9913679004f.png

(注意对比)

https://i-blog.csdnimg.cn/direct/f5e4dd5c16ab4b9494f5304a401330b5.png

3.5 内核结构图(部分)

https://i-blog.csdnimg.cn/direct/4ff6f975796d42359e1201881da85996.png

本篇分享到此结束,如果对你有所帮助,就是对小编最大的鼓励,可以的话,点赞,收藏并分享给您的小伙伴一起学习吧!

关注小编,持续更新中……