网站建设工作都干啥,1核1g可以做几个网站,php做的直播网站,建设银行手机银行下载官方网站下载文章目录第二章 进程管理进程通信#xff08;IPC#xff09;为什么进程通信需要操作系统支持#xff1f;#xff08;一#xff09;共享存储#xff08;1#xff09;基于存储区的共享#xff08;2#xff09;基于数据结构的共享#xff08;二#xff09;消息传递什么…
文章目录第二章 进程管理进程通信IPC为什么进程通信需要操作系统支持一共享存储1基于存储区的共享2基于数据结构的共享二消息传递什么叫“格式化的消息”1直接通信方式2间接通信方式三管道通信小结第二章 进程管理
进程通信IPC 这个小节我们会学习进程通信的几种方式分别是 共享存储基于数据结构的共享基于存储区的共享消息传递直接通信方式间接通信方式管道通信 进程之间的通信Inter-Process Communication, IPC是指两个进程之间产生数据交互。 在一个系统当中同时会有多个进程正在运行那么这些进程之间难免需要相互配合着工作在这种情况下进程和进程之间的数据通信就显得很有必要了。 比如正在浏览微博的时候可以通过分享功能把一条微博分享给微信好友。这时就发生进程间的通信了。本来那条微博的链接是在微博里面的直接就分享到微信里面了这个过程显然是进程和进程之间发生了数据交互、发生了通信 。 既然进程之间的通信是很有必要的那么该怎样实现进程之间的通信呢这个需要操作系统的支持。
为什么进程通信需要操作系统支持 为什么进程之间的通信一定要有操作系统内核的支持原因是这样的。 我们系统中给各个进程分配内存地址空间的时候各个进程的内存地址空间是相互独立的比如进程P它可以访问自己的空间进程Q可以访问自己的空间。但是进程P不可以访问进程Q的地址空间。 这么规定是出于安全的考虑。因为如果一个进程可以随意地访问其他进程的内存地址空间那么一个进程就可以随意修改其他进程的数据了或者随意读取其他进程的数据。那这样的话试想一下比如你的手机里面不知什么时候安装了一个垃圾软件这个垃圾软件如果它可以随意地访问其他进程的地址空间那有可能它直接把你微信里的私密的一些聊天数据或者照片之类的直接读取走了。这显然是不安全的。 因此出于安全考虑各个进程只能访问自己的这片内存地址空间而不能访问其他进程的内存地址空间无论是读、写都不行。 因此如果P和Q它们之间想要进行数据交互想要进行进程之间的通信那么显然进程P是不可能直接把这个数据写到Q的这片空间里面的。 所以由于进程不可直接访问其他进程的内存地址空间因此就必须要有操作系统的支持才可以完成进程之间的通信。 接下来会介绍三种进程之间的通信方式共享存储、消息传递、管道通信。
一共享存储
1基于存储区的共享 各个进程只能访问自己的这片空间但是如果操作系统支持共享存储的功能那么一个进程它可以申请一片共享存储区。而这片共享存储区也可以被其他进程所共享。 这样的话一个进程P如果它要给Q传送数据的话那么P就可以先把数据写到这片共享存储区里面因为P对共享存储区是有访问权限的。接下来进程Q再从共享存储区里面读出数据。 由于共享存储区可以被多个进程所共享因此这些数据之间的数据交换就可以通过这一片被共享的区域来进行。这就是共享存储的进程间通信方式。 比如Linux中如何实现共享内存 int shm_open(...); //通过shm_open系统调用申请一片共享内存区 void * mmap(...); //通过mmap系统调用将共享内存区映射到进程自己的地址空间 注什么叫内存区映射这是第三章内容。通过“增加页表项/段表项”即可将同一片共享内存区映射到各个进程的地址空间中。 另外还需要注意一个问题如果多个进程都往这片区域写数据的话有可能会导致写冲突会导致数据覆盖的问题。所以各个进程之间如果使用共享存储的方式来进行通信的话那么需要保证各个进程对这个共享存储区的访问是互斥的。也就是当进程P正在访问这片区域的时候那其他进程就不能访问这片区域。 怎么实现这个互斥的功能呢 操作系统内核会提供一些同步互斥工具比如在后面会学习的P、V操作各个进程从而能够对共享存储区实现一种互斥的访问。 刚才我们说的这种共享存储的方案是基于存储区的共享。操作系统给你划定了这么大的一片区域之后若干个进程到底是想往这片区域里的哪个位置写或者从哪个位置读这些都是很自由的。操作系统只负责把这片区域划给你但是并不管你怎么使用这片区域。 基于存储区的共享操作系统在内存中划出一块共享存储区数据的形式、存放位置都由参与通信的进程自己控制而不是操作系统。这种共享方式速度更快是一种高级通信方式。 2基于数据结构的共享 相比之下还有一种基于数据结构的共享。 操作系统给你们两个进程划定的共享区域它就规定只能存放一个长度为10的数组。这样的话各个进程之间的通信自由度就没那么高并且传送数据的速度也会比较慢。 基于数据结构的共享比如共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多是一种低级通信方式。 二消息传递 如果采用这种通信方式那么进程之间的数据交换会以格式化的消息Message为单位。通过操作系统提供的“发送消息/接收消息”两个原语来进行数据交换。 什么叫“格式化的消息” 所谓格式化的消息由两个部分组成消息头、消息体。 消息头要写明注明这个消息是由谁发送的到底要发送给谁整个消息的长度是多少等等这些概要性的信息。 消息体就是具体的一个进程想要传送给另一个进程的数据。 这种消息传递的通信方式又可以进一步划分为直接通信方式、间接通信方式。 其中直接通信方式就是发送进程要指明接收进程的ID。系统里每一个进程都会有一个ID叫PID直接通信方式的意思就是我发送的时候直接点明就是要它接收。 而间接通信方式会通过一个叫作“信箱”的中间实体来进行通信。所以间接通信方式又称为“信箱通信方式”。 1直接通信方式 进程P现在要给进程Q发送一个消息而在操作系统的内核区域是管理着各个进程的PCB的。 同时会有各个进程PCB对应的消息队列。比如进程Q就有一个进程Q的消息队列也就是其他进程要发送给进程Q、应该被进程Q接收的这些消息都挂在这个队列里面。 现在进程P要给进程Q发送一个消息。首先每个进程自己是有自己的地盘、自己的内存空间的它会在此先完善这个消息的信息如图msg包括消息头、消息体。接下来进程P会使用到发送原语send(Q, msg)操作系统提供的发送原语用它来指明我的这个消息msg是要发送给Q这个进程。 这个发送原语会导致操作系统内核接收到这个消息并且会把它 挂到进程Q的消息队列里面。 此时这个消息msg由进程P的内存空间复制到了内核空间当中。 接下来进程Q通过接收原语receive(P, msg)来指明现在要接收一个消息是P发来的。此时操作系统会检查进程Q的消息队列看一下这几个消息到底哪一个是由P发送过来的。 找到了由P发送过来的消息那么操作系统内核会把这个消息体的数据又从操作系统的内核区复制到进程Q的用户区、地址空间。 消息传递——直接通信方式点名道姓的消息传递。我在发送的时候指明要发送给谁我在接收的时候指明要接收谁发来的消息。 2间接通信方式 刚才我们说过间接通信方式它需要一个中间实体所谓的“信箱”来进行消息的传递所以又称之为信箱通信方式。 这种通信方式是这样来实现的 进程P和进程Q想要进行通信。那么进程P可以通过系统调用申请一个信箱当然也可以申请多个邮箱。比如此处进程P申请了信箱A、信箱B。 现在这两个进程怎么进行通信呢 首先进程P在自己的地址空间里完善消息msg的内容然后进程P可以使用发送原语send(A, msg)往信箱A发送消息msg。 间接通信方式是指明了我要发送到哪个信箱并没有指明我要发送给哪个进程。 那进程Q在使用接收原语的时候它可以指明我要从信箱A中接收一个消息体。这样信箱A中的这一个msg就会被操作系统复制到进程Q的空间中了。 这就是使用信箱来完成消息传递的过程。 通常来说操作系统是可以允许多个进程往同一个信箱里send消息也可以多个进程从同一个邮箱里receive消息。
三管道通信 “管道”这个词还是很形象的它就像一个水管、管道一样。就是写进程可以从管道的一边写入数据读进程从管道的另一边取走数据。 这个数据的流动只能是单向的。从左到右或者从右到左就像一根水管里的水流一样不可以是双向同时进行的。 这里的管道其实是一种特殊的共享文件又名pipe文件。也就是如果两个进程要用管道的方式进行进程通信那么首先我们需要系统调用的方式来申请一个管道文件操作系统会新建这个管道文件。这个文件的本质就是在内存当中开辟了一个大小固定的内存缓冲区。然后两个进程可以往这个内存缓冲区里面写数据和读数据但是这个数据的读写是先进先出的FIFO。 问题说到这里管道通信是为两个进程开辟了一块内存缓冲区而刚才所说的共享存储也是开辟了一块共享存储区也是可以被进程P、Q共享访问的。那么它们有什么区别 区别是这样的 刚才我们讲的基于存储区的共享进程P、Q对于共享存储区中具体的存储、读取位置没有任何限制很自由。但是管道通信的方式其中是一个数据流的形式如果前边有空位则写数据的时候要先往前边写前边占满了再接着往后边区域写读数据的时候也一样只能先把前边的数据读空了才可以读后边的这些数据先进先出。 所以管道通信和共享存储通信区别还是很大的管道通信的读写一定是先进先出的可以把它理解为一个循环队列而共享存储的读写是没有任何限制的。 1、管道只能采用半双工通信某一时间段内只能实现单向的传输。如果要实现双向同时通信全双工通信则需要设置两个管道。 2、各进程要互斥地访问管道。由操作系统实现 3、刚才已经介绍到这个管道是一个大小固定的内存缓冲区因此会被写满。当管道写满时写进程将阻塞直到读进程将管道中的数据取走即可唤醒写进程。 4、另一个方面当管道读空时读进程将阻塞直到写进程往管道中写入数据即可唤醒读进程。 5、这一点是很多教材最有争议的一个地方管道通信的方式就决定了一旦管道中的数据被读出那就彻底消失了。所以如果有多个读进程在读同一个管道的时候就有可能导致错乱因为我们管道里面的数据它并没有指明我到底是要给进程Q的、还是要给进程R的。所以如果多个进程都从同一个管道这读数据的话那么就有可能这个数据的读取动作是比较乱的第一块数据被Q读走了、第二块数据被R读走了。 针对这一问题不同的操作系统会有不同的解决方案①一个管道允许多个写进程一个读进程2014年408真题高教社官方答案②允许有多个写进程多个读进程但系统会让各个读进程轮流从管道中读数据Linux的方案。 有的操作系统是①的方案有的操作系统是②的方案。因此有的教材按照①来说管道允许多个写进程、但只允许一个读进程而有的教材按照②来说一个管道允许多个写进程、多个读进程。 对于408考试来说按照①来说即可。但是从现实应用的角度来看①②都是存在的。
小结 共享存储、消息传递、管道通信这三种常见的进程间通信方式。这三种通信的功能都是需要操作系统的底层来支持的。 共享存储会设置一块共享内存区并映射到进程的虚拟地址空间这个问题在学完第三章段表、页表之后再回来看就懂了这个很简单。 另外各个进程对共享空间的访问要互斥地进行这个互斥的效果是由进程自己进行控制的如使用P、V操作来实现。实际上对于共享存储区的互斥访问是一个经典的同步互斥问题读者、写者问题在后面会讲。 消息传递分为两种通信方式。直接通信方式就是要指名道姓地指明我要把消息发给哪个进程然后操作系统会把这个消息直接挂到接收进程的消息队列里面。 间接通信方式又叫信箱通信操作系统会把消息放到指定的信箱当中而消息的接收者也需要指明自己从哪个信箱当中取走消息。 管道通信。对于操作系统而言管道通信的这个管道是一个特殊的共享文件比如你在Linux系统上是的确能够找到这一文件的但本质上这个文件就是一个内存缓冲区如果结合数据结构的知识来看的话这个内存缓冲区其实就是一个循环队列。那么如果管道写满了写进程就会被阻塞如果管道读空了读进程就会被阻塞。 此外一个管道文件只能实现半双工通信。这类似于现实生活中的一根水管同一时刻水不可能既从左往右流、又从右往左流。 所以如果想要从左往右、从右往左的水流同时存在的话我可以建立两个管道实现双向同时通信。 读进程想要从管道读数据只需保证一点管道不是空的即可。至于管道是否写满、还是只写了一部分都无所谓只要不是空的就能读。 写进程同理只要管道没满还有空间让我可以写就可以往管道中写数据。至于管道是完全空了、还是有一部分数据都无所谓只要不满就能写。