本文转载自微信公众号「CS指南」,作者大白。转载本文请联系CS指南公众号。
中午
一个阳光明媚的中午,大白来到了领导的办公室。
大白:领导,从昨天晚上开始,我牙特别疼,我感觉我得去一趟医院...
领导:好的,你快去吧哈,最近注意身体...
当日下午
腾讯大楼,某会议室内~
大白:面试官您好,我是大白!我虽然刚工作不到一年,但是我有强悍的编程基本功以及有丰富的项目经验......
面试官:行,我大概了解了,接下来我问你点八股...不是,我们好好探讨一些底层原理。
大白:(内心:没问题,我就擅长这个,你没看过我的八股文骚套路系列吗?)好的,面试官!
面试官:先问个简单的,你讲下进程与线程的区别吧!
大白:好的,一个进程里可以包含很多线程!
面试官:没了?
大白:没了呀。
面试官:我对你的面试差不多了,你回去等结...
面试正式开始
大白:别别别,开个玩笑。其实两者区别还挺大的,先从进程讲起,我之前就写过一篇讲 Linux 进程创建 的文章...
面试官:打断一下,你那篇文章我看过,写的还不错。我问点你在文章里没提到的。你了解进程通信吗?
大白:了解呀,主要有以下几种进程通信方式:管道、消息队列、共享内存、信号量、Socket。
面试官:那你平常用过管道的方式进行进程通信吗?
大白:用过呀,经常用。管道有匿名管道和命名管道两种。我下面给您详细介绍下。
先举个例子吧,下面这条 linux 命令就运用了管道。
- echo "I'm dabai" | tee a.out
上面这条命令的具体功能是在 Linux 控制台输出 “ I’m dabai”,并且将输出的信息作为输入传递到 a.out 文件中。可以看出 I 的左边是输入,右边是输出。“|”代表的管道随着命令创建,命令执行完成后也会自动销毁.
另外一种方式就是通过 mkfifo 显示创建命名管道。
- mkfifo dabaipipe
上述命令就创建了一个名叫 “dabaipipe" 的管道。我们可以向管道中写入信息,比如:
- echo "hello ! I'm dabai" > dabaipipie
想要读取管道中的信息,采用下面的命令就可以啦!
- cat < dabaipipe
- #输出 hello ! I'm dabai
面试官:呦!还不错,那我问你什么时候该用匿名管道,什么时候该用命名管道。
大白:其实这要从匿名管道的缺点说起。匿名管道有两个缺点,这既是他的缺点也是他的特点。
(1)匿名管道仅支持父进程和子进程间的通信。
(2)匿名管道不支持跨网络的两个进程之间的通信
也正是因为这两个特点,匿名管道所需要的系统开销比命名管道小很多。(匿名管道中的文件不会写到磁盘上,而命名管道中的文件会写到磁盘上)
所以什么时候该用匿名管道,什么时候该用命名管道就很显而易见了。(快夸我)
面试官:等等,你说啥?你说匿名管道仅仅支持父进程和子进程间的通信?那你刚才这条命令 “echo "I'm dabai" | tee a.out”,谁是谁的子进程?
大白:(内心:这面试官果然不讲武德!幸亏我早有准备,就等着你跳坑了,就这个点我能给你讲到面试结束)
是这样的,匿名管道的创建过程很有意思,我给您讲一下,这样就能解答您刚才的问题。
如果要创建匿名管道,我们需要接下来的几步。
1.我们需要创建匿名管道的"管子",其实就是内核中的一段缓存。
2.为了通信,我们需要创建一个进程,然后在进程中会创建两个文件描述符指向管道的两端(一个指向输入端,一个指向输出端)。
这个时候,我们的匿名管道就变成下面这个样子了。进程想要向管道中输入数据那么就通过输入端描述符进行写入操作,想要从管道中取数据就通过输出端描述符进行读取操作。
从上面的图我们也可以看出,根本没有实现进程间通信。那么怎样实现父进程和子进程通信呢?我那篇讲进程的文章中讲过父进程创建子进程是怎么创建的,大家还记得吗?就是要用 fork。父进程通过 fork 创建子进程,子进程会把父进程的代码复制一份,这样父进程的输入端描述符子进程也复制到了。这个时候父进程和子进程都会同时指向管道。
我们再将子进程的输入关闭,父进程的输出关闭,就可以啦!
至于”echo "I'm dabai" | tee a.out “ 这条命令, | 两边并不是父子进程,那他们是怎么完成进程通信的。其实,这两个进程都是通过 shell 进程 fork 出来的。然后两个进程分别就连接到管道的输入和输出端了。再把多余的输入和输出关闭就可以啦。
最后匿名管道的结构图我就不用画了吧?(内心:这面试都一个多小时了,我还回公司蹭免费晚餐和九点下班打车呢)
面试官:要不你还是画一下吧!
大白:那好吧...就是下面这个样子!(内心:你就不急着去吃饭吗?)
面试官:小伙子可以呀,我对你挺满意的,我给你过了。本来还想详细问问你进程通信的其它几种方式,但是我得下班了。你等等下一面的面试官约你面试时间吧!
和面试官加了微信后。看了看时间,还行,还能回趟公司把餐补领了再回家,又是充实的一天。最近把进程通信其他几种方式学一学给下一面面试官讲。
参考资料:
极客时间《趣谈 Linux 操作系统》 链接:http://gk.link/a/10zn1
《Linux系统编程、网络编程》第7章 进程间通信(本机IPC) 链接:https://www.bilibili.com/video/BV1fE411v7Bb
JavaGuide 操作系统篇 链接:https://snailclimb.gitee.io/javaguide/#/docs/cs-basics/operating-system/basis