什么是进程间通信

为什么要有进程间通信 

        为什么要有进程间通信, 为什么一个进程要给另一个进程发送数据? ——发送基本指令、发送命令、某种协同、通知。——是为了让多个进程之间相互协同起来。这就有了基本的需求, 所以最终就转化为了如何让进程之间通信起来。 

如何让进程完成通信

        然后上面知识基本的是什么为什么, 现在我们要谈论的细节就是, 通信是有成本的, 这个成本主要体现在要打破进程间的独立性。

        而又因为我们进程间是独立的, 所以又不能过度的破坏进程间的独立性。 

        所以, 怎么办才能让进程间完成通信呢?

        首先我们必须知道, 进程间通信的本质——必须让不同的进程看到同一份“资源"

        其次, 有一个"资源”特定形式的内存空间——并且进程一个往里写, 一个往里读——什么意思呢, 怎么理解这个“资源”呢? 就类似于电视剧里面的绑匪, 电视剧里面的绑匪会与被绑架者的家属约定一个地点, 然后说让家属扔一百万到旁边的垃圾桶。 这个家属呢, 扔完钱就可以走了, 之后绑匪就去取这个钱。 这个故事里面的家属和绑匪, 就是两个进程, 而这个垃圾桶就是资源。 当家属将钱放到垃圾桶, 就类似于一个进程向资源中写入, 当绑匪拿到钱, 就类似于另一个进程从资源里获取资源

        我们进程访问这个空间, 进程通信, 本质就是访问操作系统!!!——因为这个空间是由操作系统提供的, 因为进程是用户启动的, 所以进程代表的就是用户, 那么问题来了, 我们说过, 群众之间有坏人, 而操作系统并不相信用户。 所以呢, 我们的资源从创建, 到使用, 到终止(释放)这个过程, 并不允许我们的进程直接访问资源, 而必须使用对应的系统调用!!!

 管道

 认识管道

        首先我们知道, 一个文件是能够被一个进程打开的, 但是问题是:一个文件能否被多个进程打开呢?——答案是可以的, 那么既然我们的文件能够被多个进程所打开, 那么只要我们的一个进程向文件里面写, 一个进程向文件里面读。 ——其实就是一个进程向文件里面刷新数据, 刷新到磁盘, 然后另一个进程向文件里面读, 就完成了进程的通信。 

        但是这种方式因为是将我们的数据写到外设里面, 所以这个就一定会伴随着很多很多的效率问题。

文件原理

为了方便讲解原理, 这里我们先将图放出来, 以便讲解:

         知道了上面的知识之后, 我们考虑一个问题, 就是我们如果磁盘中, 根本没有文件, 但是我们今天要打开它。也就是说, 我们今天打开一个文件, 这个文件在文件中有他的inode, file_operators, 文件页缓冲区。 但是呢, 在我们的磁盘中并没有这个文件时, 这个文件真正的变成了一个内存级文件, 请问, 这个可不可行?——现在我们就来谈一谈这种文件的可行性。

管道原理

单进程内存级文件

        原本的我们的文件的file_operators保存的是硬件层面的接口, 并且操作系统要让内存中的数据向磁盘中进行刷新。 如今呢, 我们的file_operators直接保存软件层面的接口, 也就是内存级层面的接口了, 操作系统也不需要让内存中的数据向磁盘中进行刷新了。 

        其实我们的管道本质上就是上面的内存级文件。 

        内存级文件的原理,或者说是管道的管理其实和磁盘文件级文件的管理是有相同的地方的。 linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

        上图的左边部分,我们知道, 是属于进程的部分。 而内存级文件和磁盘级文件的不同是属于文件系统的部分。 所以显然左边部分和上面学习的文件原理是一样的。 那么我们区别就是右边部分。 右边部分的区别是我们没有磁盘文件向文件缓冲区写入数据了。 而改成了我们的进程拿到file_operators,使用file_operators向文件缓冲区中写入数据

带有父子进程的内存级文件

linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

当我们的一个进程创建出一个子进程, 那么就要创建PCB, 地址空间, 文件描述符等等。 

        linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

        但是, 我们的文件struct file需不需要拷贝给子进程呢?——但是不需要, 因为要知道, 我们的文件, 是属于系统的, 是有系统打开的, 并不是属于这个进程的。 我们进程与文件(这里的文件指的是内存里面的文件struct file)之类的关系, 并不是从属的关系。而是关联的关系, 我们的进程所有的file_struct 可以找到struct file, 可以使用struct file的file_operators接口, 可以修改数据到内存, 但也仅此而已!!!而且, 我们的操作系统也说过——操作系统的管理一般分为:进程管理, 驱动管理, 内存管理, 文件管理。 可见, 进程和文件之间是并列的关系, 并不是从属的关系。

linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

        那么, 再思考一个问题, 为什么我们的文件描述符表也要有呢?——因为文件描述符表是我们当前进程打开文件的列表——而父进程和子进程并不是同一个进程, 而且又有相同的内容,所以子进程就要拷贝父进程一份file_struct。——这也就是为什么我们的父进程打印, 我们的子进程也打印, 但是两个会同时向我们的同一个终端打印的原因。

linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

管道的形成

        如果今天, 我们的进程打开了一个内存级文件, 那么如果这个进程又创建了一个子进程, 这个时候父进程会指向同一个struct_file, 那么如果父进程想要向子进程进行通信, 那么只要父进程将数据写到我们的文件页缓冲区, 然后子进程从文件页缓冲区进行读取, 那么是不是就能够将数据读取到了?就完成进程间的通信了。

        管道的本质也叫做文件!!!管道就是文件, 只不过管道文件不是我们理解的磁盘文件。 

        但是这里有一个问题, 就是当我们的父子进程进行通信的时候, 如果一方不下心将文件关掉了, 那么会不会影响另一个呢?——答案是不会的, 因为我们的struct_file里面包含了一个int cnt的引用计数, 只要当我们有一个文件描述符指向struct_file的时候, 对应的struct_file就会加加。 也就是说, 父子进程都打开这个文件的时候, 这个文件的应用技术就一定会大于等于2!所以一个进程关掉文件后不会影响另一个进程。

        我们的父进程在系统中打开管道文件的时候, 并不只是把文件单方面的打开或者读或写, 而是打开这个管道文件的时候, 对于这个管道文件,既以读的方式打开, 又以写的方式打开。

linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

然后父进程再创建子进程, 子进程拷贝文件描述符表。 ——所以, 父进程和子进程都有对应的读写段指向同一个文件。        linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

然后我们就要结合具体场景, 确定我们的两个进程到底是读, 还是到底是写。 ——这就要求我们的父子进程分别关闭一个读写段, 形成一个单向的通信信道。 ——比如父进程关闭读, 子进程关闭写。 父进程用来写入, 子进程用来读取。 ——又比如父进程关闭写, 子进程关闭度。 父进程用来读取, 子进程用来写入。 

        那么我们站在内核的角度, 管道的本质是什么呢。

        现在的情况是, 我们的父进程和子进程都有读有写。 那么这个缓冲区里面的数据就不知道是谁的了。 所以我们的设计者就规定——我们只想让父子进行单向通信。 然后由用户规定谁给谁通信。

        我们这里假如规定成子进程写入, 父进程读取。

        以上, 就是管道通信的本质。 而之所以叫做管道, 是因为它只能进行单向通信!——而为什么是单向通信的, 第一是因为它是基于文件通信的, 第二是因为设计者为了图简单。 ——所以就有了管道的名字。 如果我们要进行双向通信呢?——就用多个管道。

        上面讲的是父子进程层面的, 但是我们如果两个进程没有任何关系, 可以使用我们刚刚讲的原理进行通信吗?不能!——这里的管道的形成, 必须是有血缘关系的!!!——比如爷孙, 比如父子。

——以上就是本篇的全部内容, 本篇内容到此就结束啦, 感谢友友的阅读, 下面是本节的笔记, 和正文几乎一样的, 觉得本节内容有用的话可以保存方便查阅哦

linux进程间通信——进程间通信概念、最基本通信——管道文件-LMLPHP

09-10 08:38