进程间通讯

本文详细介绍了进程间通信(IPC)的常见方式,包括管道(匿名和命名)、消息队列、共享内存、套接字(用于网络通信)以及信号和信号量。管道是早期UNIX系统中采用的通信手段,而消息队列和共享内存解决了数据传输效率和内核态转换的问题。套接字则使得跨计算机的进程间通信成为可能。信号量作为同步和互斥的工具,确保了对共享资源的正确访问。这些机制构成了现代操作系统中进程通信的基础。
摘要由CSDN通过智能技术生成

进程间通讯是进程之间协作的必要部件,随着不断发展,也有许多种类的进程间通讯出现。
之前一直没有系统的进行梳理,正好最近在网上发现一篇讲的不错的文章,于是打算以此做为大纲,梳理一下进程间通讯的几个方式
先贴文

凉了!张三同学没答好「进程间通信」,被面试官挂了…_小林coding的博客-CSDN博客

简单的总结一下各个通讯方式的特点:

1.管道

为满足进程间通讯,早期UNIX系统最早使用的就是管道,管道就是内核空间内存里的一部分内存。

其实,所谓的管道,就是内核里面的一串缓存。从管道的一段写入的数据,实际上是缓存在内核中的,另一端读取,也就是从内核中读取这段数据。另外,管道传输的数据是无格式的流且大小受限。

有些地方(如介绍linux和UNIX的一些书籍),介绍管道为“本质也是特殊文件”,这种说法是没有错的,因为使用管道的进程通过文件描述符进行读写,进程将其视作一个文件,这其实是Linux构建思想中的“一切皆文件”。
管道对用户进程来说就可以认为是一个虚拟文件,所谓虚拟,就在于本质并非磁盘中的文件,而是内核中的一部分内存。
管道通信:深入理解“linux 一切皆文件”的思想

关于管道的一些细节和问题

管道的创建
管道作为虚拟的文件,在文件系统中是没有相应的映像的(只有磁盘文件才有),因此需要使用pipe()调用创建新管道——这个调用返回一对文件描述符,代表入口和出口。
关于命名管道(FIFO)和匿名管道的区别
表现上,命名管道可以被多个无父子关系的进程使用,匿名必须有父子关系。
究其原因,在于命名管道创建和匿名管道的不同
匿名管道会被组织成一个独立于文件系统的,被称作pipefs特殊文件系统——但注意,其他用户程序看不到他,整合的目的只是为了适应以文件方式操作,从这个角度看,可以说pipefs文件系统是对真正文件系统的一个模仿。
image.png
而命名管道(FIFO)创建时,会在文件系统树中创建磁盘索引节点,这个文件名将被包含在目录树中,从而任何进程都能访问命名管道——因为全部进程都能访问文件系统树。
image.png

关于进程对管道相关的内存访问
管道涉及的内存在内核空间中,因此想对其读写的进程需要使用系统调用访问——因为在进程看来是文件,因此使用的系统调用不是其他,正是和文件相关的read()和write()。
关于管道涉及的内存的形状
管道在内核空间中是一个环形缓冲区,

2.消息队列

管道的通信方式是效率低的,因此管道不适合进程间频繁地交换数据。
为了解决这个问题,使用保存在内核中的消息链表代替在内核中的环形缓冲区
消息队列也有其的缺点,这个缺点和管道是一脉相承的,主要导致原因就是使用了内核空间中的内存,这导致每次数据传输都要从用户态拷贝数据到内核态。

3.共享内存

为解决内核态转换问题,共享内存利用os实现的虚拟内存机制,将两个进程的一部分内存映射到同一个物理内存空间。
aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS85MWQwMjBiMy1lMmQ3LTRhZmEtOWY5YS00OWI2ZWRiMDU4ZWUucG5n.png
共享内存的想法其实是消息队列和管道的延伸
我们要注意到,进程的内核空间本质上是全部进程共享的,因为在切换进程的时候,内核空间占有的对应虚拟内存段将不会被切换,只有用户空间对应的才会被切换。
而对于共享内存,由于映射关系相同的原因,即使切换到不同的用户空间,那段特殊的共享内存在逻辑上相当于没有被切换。
从这一点看,共享内存对应的内存片段确实类似内核空间——只是它没有了严格限制的内核权限,更加方便。

4.套接字(Soket)

前面几种方式解决一个计算机内的进程通讯间文件,为解决不同计算机进程的通讯,人们发明了套接字。
套接字本质是一个数据结构,包含通讯目的地地址,端口号等信息,每个进程有着独特的套接字号,以此区分彼此。
一类套接字允许不同计算机的进程通过网络交换数据。

  • 基于网络型,此类套接字使用分对称方式通讯,类似网络通讯。

当然,也有一类套接字能向下兼容计算机内部进程的通讯。

  • 基于文件型,此类套接字基于本地文件系统支持,实现过程类似管道。

5.信号

信号在最早的Unix系统中即被引人,用于在用户态进程间通信。内核也用信号通知进程系统所发生的事件。信号已有30多年的历史,但只有很小的变化。
信号定义
信号(signal)是指很短的消息,可以被发送到一个进程或一组进程。发送给进程的唯一信息通常是一个,以此来标识信号。
信号目的
使用信号的两个主要目的是:

  • 让进程知道已经发生了一个特定的事件。
    
  • 强迫进程执行它自己代码中的信号处理程序。
    

当然,让进程知道事件已经发生,进程就可能会做出一些反应,因此这两个目的通常会都被实现。
信号特点
信号是进程间通信机制中唯一的异步通信机制,因为可以在任何时候发送信号给某一进程,一旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式。
进程对信号的响应
进程对信号有三种响应方式,比较类似于一些代码中对异常的处理方式:

  • 执行操作
  • 捕捉该信号
  • 忽略此信号

6.信号量

严格来说,信号量不算通讯方式,它是为了解决共享数据竞争问题,因此算保证进程间通讯正常运行的必要的一个机制。
信号量保证解决如下竞争问题。

  • 互斥的方式,可保证任意时刻只有一个进程访问共享资源;
  • 同步的方式,可保证进程 A 应在进程 B 之前执行;

进程使用信号量时异常终止发生的事
进程使用信号量实际上有一个问题,就是进程异常中断而无法由它手动释放持有的信号量。不解决这个问题会导致信号量最终陷入不足的境地,其他进程将会无限停留在阻塞状态。
内核对其的解决方式就是使用一种失效安全机制——进程本身会在一个sem_undo数据结构中存放自己获得的各种信号量的值,当内核发现进程错乱,则会访问这个结构,简单的还原被修改的信号量。

关于IPC(Inter-Process Communication)

IPC(Inter-Process Communication)是指多个进程之间相互通信,交换信息的方法,实际上在操作系统内部,信号量,消息队列或者信号都被视作属于这些机制。

  • 通过信号量与其他进程进行同步
  • 向其他进程发送信号或者从其他进程接受信号
  • 和其他进程共享一段内存区

可以看到,这些机制其实就是上面谈到的几类方式。
IPC机制的运行
内核有着提供这些机制元素的函数,调用这些函数,进程就相当于请求IPC资源,内核创建了对应的结构之后,分配给进程IPC标识符,进程就能随时访问资源了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值