目录

Linux进程间通信

【Linux】进程间通信

1. 通信

  • 通信概念:两个或者多个进程实现 数据 层面的交互

    因为进程独立性的存在,导致进程通信的成本比较高

  • 进程间通信的本质 :必须让不同的进程看到同一份”资源”——特定形式的内存空间。

  • 这个”资源”谁提供?一般是 操作系统

    为什么不是我们两个进程中的一个呢?假设一个进程提供,这个资源属于谁?这个进程独有,破坏进程独立性。

  • “资源”从创建,使用,释放,都是使用系统调用接口!

  • 基于文件级别的通信方式——–管道

进程间通信目的:

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

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

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

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

2. 匿名管道

2.1 匿名管道的原理

管道就是文件

https://i-blog.csdnimg.cn/direct/05843de2b3f74ef3b4cbb396a85cdb8f.png

现在还要一个问题。

如果父进程只是以写或读的形式打开文件,那么子进程也只能是以写或读的形式打开文件,所以父子只能同时读或写。但是我们需要父写子读 或 父读子写。那么只能如下操作:

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

https://i-blog.csdnimg.cn/direct/89c30c087c8e4842b435df9f9acbea3f.png

https://i-blog.csdnimg.cn/direct/692b4037e01a48a4ae078884bc88ce74.png

真正的管道通信原理:

也说明了管道只能进行单向通信。

https://i-blog.csdnimg.cn/direct/56a835de870b4581a40429820d71c89c.png

  • 如果我要进行双向通信呢?使用多个管道

  • 如果没有任何关系,可以用我们刚刚讲的原理进行通信呢?不能

    必须是父子关系,兄弟关系,爷孙关系…——–血缘关系,常用于父子

  • 因为管道的内存级文件是匿名的,所以叫做匿名管道‘

2.2 匿名管道的有关代码编写

2.2.1 匿名管道代码编写

https://i-blog.csdnimg.cn/direct/3fd9f908d2154a46b818421a05be400a.png

管道的特征:

  • 具有血缘关系的进程进行进程间通信
  • 管道只能单向通信
  • 父子进程是会进程协同的,同步与互斥的——保护管道文件的数据安全
  • 管道是面向字节流的
  • 管道是基于文件的,而文件的生命周期是随 进程 的!

代码gitee链接:

管道的4种情况:

1.读写端正常,管道如果为空,读端就要阻塞

2.读写端正常,管道如果被写满,写端就要阻塞

3.读嘴正常读,写端关闭,读一段时间后,读端就会读到0,表明读到了文件(pipe)结尾,不会被阻塞

  1. 写端是正常写入,读端关闭了。操作系统就要杀掉正在写入的进程。如何干掉? 通过信号杀掉 。杀掉因为操作系统是不会做,低效,浪费等类似的工作的。

通过13号信号—– SIGPIPE 杀掉进程

2.2.2 进程池代码

gitee代码:

3. 命名管道

3.1 创建命名管道的函数

创建命名管道的函数:

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

https://i-blog.csdnimg.cn/direct/1b7cfeed7e4c48e390017b7aed331e7b.png

3.2 命名管道的原理

具有血缘关系的进程使用匿名管道,没有血缘关系的进程则使用命名管道。

如果两个不同的进程打开同一个文件的时候,在内核中,操作系统只会打开一个文件。

因为该管道文件不需要刷盘,所以直接创建内存级文件。

如何打开同一个文件,文件的文件名+路径相同即可。

https://i-blog.csdnimg.cn/direct/36f901fc5dc246c8b9b85a21df40c44b.png

3.3 命名管道代码的编写

gitee链接:

内含日志代码编写

4. system V共享内存

4.1 system V共享内存的原理

再次强调:进程间通信的原理是让进程看到同一份资源

https://i-blog.csdnimg.cn/direct/5baed784dfbf4e9182625f7cd6e48337.png

如果要申请共享内存、释放共享内存、关联、去关联—–这些操作都是进程直接做的吗?不是。直接由操作系统来做。

需求方—> 系统调用 —> 执行方

4.2 相关函数

4.2.1 shmget 函数

作用:为共享内存申请空间

https://i-blog.csdnimg.cn/direct/2e55c4d8728842b7a681eb2706162424.png

4.2.2 ftok函数

作用:用pathname和proj_id确定一个key

https://i-blog.csdnimg.cn/direct/0e0f8313250a4ca08db3e7c193605a64.png

  1. key是一个数字,这个数字是几,不重要。关键在于它必须在内核中具有唯一性,能够让不同的进程进行唯一性标识
  2. 第一个进程可以通过key创建共享内存,第二个之后的进程,只要拿着同一个key就可以和第一个进程看到同一个共享内存了!
  3. 对于一个已经创建好的共享内存,key在哪?key在共享内存的描述对象中!
  4. 该函数使 key 的矛盾冲突较小
  5. 当路径不存在时,key就会返回-1;当key与系统中的共享内存相同时,就需要更改pathname或proj_id;

4.2.3 查看和删除共享内存

共享内存的生命周期是随内核的!

用户不主动关闭,共享内存会一直存在。

除非内核重启(用户释放)

https://i-blog.csdnimg.cn/direct/3391370f1095422285559a3b213970b8.png

key:操作系统内标定唯一性

shmid:只在你的进程内,用来表示资源的唯一性!

4.2.4 shmat 函数

https://i-blog.csdnimg.cn/direct/50fb1b0527fe4f7cb8906470302bd30e.png

4.2.5 shmctl 函数

作用:删除共享内存

https://i-blog.csdnimg.cn/direct/370e3653b120466ea01148302a9e1439.png

4.3 共享内存的性质

  1. 共享内存没有同步互斥之类的保护机制
  2. 共享内存是所有的进程间通信中,速度最快的!因为拷贝少,管道要拷贝2次,共享内存1次也不用
  3. 共享内存内部的数据,由用户自己维护!

4.4 共享内存代码编写

链接如下:

,其中利用了管道解决了共享内存同步问题。

5. 消息队列

5.1 消息队列的原理

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

6. IPC在内核中的数据结构设计

使用 C的方式继承 的方法。

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