Linux进程间通信10分钟快速入门

在Linux环境下运行程序,无论是点击桌面上的一个图标,还是在命令行下敲击一个shell命令,Linux系统都会把我们的程序“包装”成一个进程的形式,然后调度运行:每个进程轮流占用CPU一段时间去执行,时间到了就让给其它进程,时间片轮转,只要轮转得速度足够快,就会给用户一种错觉:我们在电脑上一边听歌,一边打字,感觉多个程序在同时运行。不同进程在运行过程中,根据业务需要,进程相互之间也会通信:比如传输数据、发送信号等。

Linux环境下的进程间通信(Inter-Process Communication,简称IPC)有多种工具可以使用,如:无名管道pipe、命名管道FIFO、消息队列、共享内存、信号量、信号、文件锁、socket等。这些IPC工具以系统调用或库函数API的形式提供给用户使用:用户使用这些API可以在不同的进程之间传输数据、同步进程、或者发送信号。比如,我们可以使用ctrl+C组合键去终止一个进程,或者使用shell命令kill 3567去杀死一个进程pid为3567的进程,这些其实都是给进程发送信号,进程接收信号并进行处理的过程。

不同的IPC工具,使用场合不同,各有优劣。为了更好地使用它们,我们不仅要熟练掌握API接口的使用,还要对它们的通信机制、内核实现原理有一个大致的了解。只有掌握了底层的实现原理、我们才能明白每个IPC通信工具的优点和缺点、以及他们的使用场合。想要真正理解Linux进程之间到底是如何通信的,首先要搞明白Linux下的不同进程在运行过程中,在内存中是以什么样的形态存在的,以及与Linux内核之间是如何交互的。想要理解这点,我们还需要对Linux环境下程序的编译、执行过程有一个大概的了解。

1 程序的编译和执行

当我们在桌面上点击一个图标,或者在命令行下敲击一个shell命令运行时,Linux系统会把这些可执行文件加载到内存,并封装成一个进程,然后才能参与操作系统的调度、运行。那操作系统是如何加载的呢?

1564654740303.png

首先,我们编写的C语言源代码会编译成一个可执行文件(ELF)。可执行文件分由各种不同的段(section)组成:代码段、数据段、BSS段等。我们C程序中的不同代码会被编译到不同的段中:函数实现会放到代码段;全局变量、静态局部变量会放到数据段;未初始化的全局变量会放到BSS段中......

加载器加载程序到内存执行,一般分2步走:第一步,会首先使用fork去创建一个子进程,每个子进程有4G的虚拟地址空间。第二步,从磁盘上软件安装的位置,去读取可执行文件的头部:ELF header,获取各个段的信息,然后分别将不同的段加载到进程空间的不同位置,如上图所示。

在一个计算机系统中,通常会有多个进程同时运行,每一个进程差不多都是通过上面这种 fork-exec 的方式运行的。当运行的进程多了,每个进程都想霸占CPU、独享CPU,CPU的资源就不够用了,这个时候操作系统就开始登场了。操作系统扮演一个调度者的角色,协调各个进程轮流占用CPU运行。

1564656367916.png

如上图所示,对于用户运行的不同进程,在内核空间,会有一个专门的数据结构来表示:task_struct。这个结构体描述了进程的各种信息,不同的task_sruct结构体通过链表串起来,内核通过链表就可以对这些进程进行管理。操作系统会有一个叫调度器的核心组件,每隔一段时间(一般是毫秒级)会有一个定时器中断,Linux调度器就会把正在运行的进程从CPU上赶下来,接着让另一个进程去执行,如此反复,周而复始。只要CPU的速度足够快、轮流执行的频率足够高,对于用户来说,就感觉多个程序同时运行。

2 进程的地址空间

每一个进程,都有一个4G大小、独立的虚拟地址空间,然后通过页表映射,映射到物理内存的不同位置上。CPU执行不同的进程时,根据每个进程的映射页表,就会到其对应的物理内存上一条一条地取指令、翻译指令、运行指令。

1564656641206.png

如上图中的进程A和进程B,它们在内存中有相同的4G虚拟地址空间,但是每个进程通过各自的页表映射,就映射到了物理内存中的不同位置。也就是说,每个进程的虚拟地址空间虽然是相同的,但是它们在物理内存空间上却是相同隔离的、相互独立的。在每个进程的4G虚拟地址空间中,[0,3G]这段地址空间是每个进程独有的,而[3G,4G]这段空间是被内核占用的,不同进程的[3G,4G]这段空间都被内核占用。内核本身在运行时,在物理内存上也会有自己单独的存储空间。

1564657079518.png

3 Linux进程间通信的三种方法

通过上面的学习我们可以看到,用户空间的不同进程,它们在时空上是相互隔离、相互独立的,如同黑夜和白天,太阳和月亮,永远不会见面,老死不相往来。但万事没有绝对,各个进程之间如果真想通信,还是有方法的,如下图所示。

1564658539689.png

用户空间的每个进程虽说在物理内存空间上是相互隔离、相互独立的,但通过内核空间这一共享区域,它们还是可以相互通信的。只要内核愿意、提供一些空间,不同的进程之间就可以对这块内存空间读写数据,达到进程间通信的目的。磁盘也是公共存储空间,不同进程也可以通过往磁盘上某个指定的文件读写数据完成进程间的通信。除此之外,不同的进程之间,如果事先商量好,也可以绕过内核,通过内存映射,在物理内存上建立一片共享内存,直接进行通信。

4 无名管道pipe通信机制

以Linux的无名管道pipe通信机制为例:无名管道常用于有血缘关系的进程之间的通信,我们可以通过pipe系统调用去创建一个管道:

int pipe (int  pipefd[2]);

该函数会创建一个管道,这个管道有两个文件描述符,一个用来读,一个用来写,不同进程可以通过读写描述符对这个管道进行读写,达到进程间通信的目的。

1564660602383.png

无名管道在内核中的实现其实很简单,就是Linux内核空间的一片缓冲区,通过pipefs机制把它封装成一个文件的形式,留出文件的读写接口:文件描述符给用户空间进程。用户空间的不同进程通过这一对读写描述符就可以对管道进行读写。

1564660740725.png

5 更多的进程间通信工具

除了无名管道外,Linux提供了很多进程间通信的工具可以使用,比如:命名管道FIFO、信号量、消息队列、共享内存、信号signal、socket、Dbus等。不同的IPC工具有各自的优缺点、使用场合。比如无名管道只能用于亲缘关系的进程间通信,命名管道PIPE解决了这一局限,支持任意两进程之间的通信;消息队列可以支持有数据格式的通信,共享内存效率最高,但是需要跟信号量、锁等同步机制结合使用;信号主要用于进程间的异步通信,也是唯一的一种异步通信机制。

每一种IPC通信工具,都有自己的优缺点、使用场合和局限,我们只有全面了解和掌握各个IPC工具的使用,知晓其优缺点,才能在实际的工作中根据需要,选择合适的通信机制。除了这些POSIX/system V标准接口定义的IPC工具外,Linux系统还扩展了一些自己独特的API,如signalfd、timerfd等,解决了信号通信机制的一些缺陷。想要进一步了解这些IPC工具接口的使用和实现机制,可以关注教程:《Linux系统编程》第05期:进程间通信,目前已经录制完毕,已在各大平台陆续上传,已经通过淘宝预售购买的同学可以直接下载学习了:淘宝店

image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容