首页 > 系统相关 >图解Linux进程间通信实现原理(1)

图解Linux进程间通信实现原理(1)

时间:2022-11-29 10:04:18浏览次数:43  
标签:节点 间通信 索引 管道 内存 Linux 进程 图解 连接

为Linux应用程序的开发人员,对Linux的进程间通信方式肯定是了如指掌,平时的开发中应该会大量的使用到。当你迅速的在键盘上按下【CTRL+C】终止掉一个正在运行中的命令时,你有没有仔细的思考过背后的原理呢?或者是他们是通过什么通信方式呢?这个通信方式是怎样实现的呢?本文就带着大家去Linux进程间通信一探究竟,找出他们的原理。

概念

我们都知道,应用程序在运行起来之后(进程),是相互独立的,都有自己的进程地址空间。但是往往在一些业务上需要进程间的通信,来完成系统的某个完整的功能。我们来看下进程间通信能干那些事情?首先当然最重要的是:

  1. 数据传输。一个进程需要发送数据到另一个进程,这种需求肯定是存在的。
  2. 共享数据。如果有多个进程想要访问数据,一个进程修改了内容,另一个进程能够立即看到内容变化。
  3. 资源保护:上面的的操作中存在竞争情况,内核需要提供锁和同步机制。
  4. 通知:一个进程需要向另一个进程发送消息,通知发生了某个事件。
  5. 控制:有些进程需要控制另一个进程的运行。典型的例子就是gdb,可参考之前文章【gdb到底是怎么实现的?】

 

通信方式

进程间的通信方式一般可以分为八种,如下:

 

八种通信方式

 

他们在不同的标准都有不同的实现,如下图所示:

 

通信方式框图

 

 

我们先从管道开始讲起来吧。

管道

这里说的管理特指的是无名管道,它是一种半双工的通信方式。也就是说数据只能单向流动,一般是在具有亲缘关系的进程间使用,比如父子进程。当一个进程创建了一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式。

管道是怎么通信的呢?

首先管道是内核的一个缓冲区,而且是在内存中。管道一头连接着一个进程的输出,另一头连接着另一个进程的输入。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。看下图:

 

 

 

那管道怎样建立的呢?

从原理上,管道利用fork机制建立,从而让两个进程可以连接到同一个PIPE上。最开始的时候,上面的两个箭头都连接在同一个进程1上(连接在进程1上的两个箭头),如下图。当fork复制进程的时候,会将这两个连接也复制到新的进程(进程2)。随后,每个进程关闭自己不需要的一个连接 (两个黑色的箭头被关闭; 进程1关闭从PIPE来的输入连接,进程2关闭输出到PIPE的连接),这样,剩下的红色连接就构成了如上图的PIPE。

 

 

 

 

管道在内核中具体怎么实现的呢?

在Linux内核中,并没有针对管道新增数据结构。而是巧妙的借用了文件系统的file结构和虚拟文件系统的索引节点inode。通过将两个 file 结构指向同一个临时的 VFS 索引节点,而这个 VFS 索引节点又指向一个物理页面而实现的。

 

 

 

具体实现

管道的实现其实也不难,源代码在内核工程中的fs/pipe.c,我们着重的讲两个比较重要的接口吧,也就是常用的pipe_read()和pipe_write(),前者是管道读函数,后者是管道写函数。

管道写函数将字节数据复制到虚拟文件系统索引节点指向的物理内存页,而读函数则是相反:读出数据。当然这里存在着竞争的管理,需要一定的同步机制,使用锁,等待队列和信号。

当我们写的时候,调用write(),内核根据传入的文件描述符fd,找到该文件的file结构。然后执行结构中f_op中的写函数。写函数在向内存写入数据之前,必须首先检查虚拟文件系统索引节点信息,检查是否有足够的内存空间可以写和内存没有被读程序锁定这两个条件,只有满足了,才真正的进行内存拷贝。

接下来写函数就会锁定内存,然后复制数据到内存,否则就在虚拟文件系统inode的等待队列中。

管道的读取过程和写入过程类似。但是,进程可以在没有数据或内存被锁定时立即返回错误信息,而不是阻塞该进程,这依赖于文件或管道的打开模式。反之,进程可以休眠在索引节点的等待队列中等待写入进程写入数据。当所有的进程完成了管道操作之后,管道的索引节点被丢弃,而共享数据页也被释放。

总结

由于篇幅的限制,八大进程间通信只讲了管道,文章开头的疑问也只能等到后续文章了,也算是留个悬念吧。

 



标签:节点,间通信,索引,管道,内存,Linux,进程,图解,连接
From: https://blog.51cto.com/u_15707676/5894069

相关文章

  • Linux基础环境配置————新手篇
    在大家安装系统之后一些基础的命令是不存在的,这个时候需要我们配置环境首先大家可以设置静态的IP具体操作如下首先我们切换root权限su输入密码后切换root权限然后输......
  • Linux应急响应技巧整理
    留存备用Linux环境下处理应急响应事件往往会更加的棘手,因为相比于Windows,Linux没有像Autorun、procexp这样的应急响应利器,也没有统一的应急响应处理流程。所以,这篇......
  • 4 在Linux Centos客户端连接SMB群辉NAS的共享
    1.1    在NAS中开启SMB1的支持:1.2    最主要的是用命令行: [root@localhost~]#sudomount-tcifs​​//192.168.1.20/XXXXX/研发中心/AI算法部/AI算法共享......
  • Linux系统中解决Device eth0 does not seem to be present,delaying initialization问
    参考的第一篇文章前言CentOS6.5已安装好一台CentOS6.5虚拟机,假定为A。在A上执行克隆操作,获得B。在B启动后,遇到错误Deviceeth0doesnotseemtobepresent错误原因......
  • Linux getenforce 命令
    Linux命令是对Linux系统进行管理的命令。对于Linux系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与......
  • GitLab的安装及配置(Linux和Windows)
    GitLab是由GitLabInc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。对于每次推或提......
  • linux 下好用的命令行工具(持续更新)
    tldr你能通过这个工具,快速查看查看各种命令的常用命令行例子clochtopsudoaptinstallhtoppowerline一个非常好看的导航栏美化工具有关安装方法请见这篇博客:dee......
  • 进程间通信的6种方式
    1、管道:1)管道传输数据是单向的,如果想相互通信,需要建立两个管道。2)管道这种通信方式效率低,不适合进程间频繁地交换数据。3)优点是简单,很容易得知管道里的数据已经被另一......
  • Arthas之Linux实践
    注意:要用Java进程拥有者去运行arthas,否则权限不够无法监听--查看Java进程拥有者ps-ef|grepjava|awk{'print$1'}--通过grep过滤查看并确认Java进程号ps-ef|......
  • linux死机
    请教,我用的MT7621双核CPU,经常出现stallonCPU的情况,<3>INFO:rcu_sched_statedetectedstallonCPU0(t=2500jiffies)<3>INFO:rcu_bh_statedetectedstallsonCPUs......