【操作系统】每日 3 题(二十二)
✍个人博客:https://blog.csdn.net/Newin2020?type=blog
📣专栏地址:https://blog.csdn.net/newin2020/category_12820365.html
📚专栏简介:在这个专栏中,我将会分享操作系统面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
64. 进程间通信方式 - 匿名管道
匿名管道顾名思义,它没有名字标识,匿名管道是特殊文件只存在于内存,没有存在于文件系统中,shell 命令中的「|」竖线就是匿名管道,通信的数据是无格式的流并且大小受限,通信的方式是单向的,数据只能在一个方向上流动,如果要双向通信,需要创建两个管道,再来匿名管道是只能用于存在父子关系的进程间通信,匿名管道的生命周期随着进程创建而建立,随着进程终止而消失。
- 匿名管道特点:
- 匿名管道是一种特殊的文件,这种文件只存在于内存中。
- 匿名管道只能用于父子进程或兄弟进程之间,必须用于具有亲缘关系的进程间的通信。
- 匿名管道只能由一端向另一端发送数据,是半双工方式,如果双方需要同时收发数据需要两个管道。
- 相关接口:
- int pipe(int fd[2]);
- fd[2]:管道两端用 fd[0] 和 fd[1] 来描述,读的一端用 fd[0] 表示,写的一端用 fd[1] 表示。通信双方的进程中写数据的一方需要把 fd[0] 先 close 掉,读的一方需要先把 fd[1] 给 close 掉。
- int pipe(int fd[2]);
65. 进程间通信方式 - 有名管道
命名管道突破了匿名管道只能在亲缘关系进程间的通信限制,因为使用命名管道的前提,需要在文件系统创建一个类型为 p 的设备文件,那么毫无关系的进程就可以通过这个设备文件进行通信。另外,不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则,不支持 lseek 之类的文件定位操作。
- 有名管道特点:
- 有名管道是 FIFO 文件,存在于文件系统中,可以通过文件路径名来指出。
- 有名管道可以在不具有亲缘关系的进程间进行通信。
- 相关接口:
- int mkfifo(const char *pathname, mode_t mode);
- pathname:即将创建的 FIFO 文件路径,如果文件存在需要先删除。
- mode:和open()中的参数相同。
- int mkfifo(const char *pathname, mode_t mode);
在 shell 里面执行 A | B命令的时候,A 进程和 B 进程都是 shell 创建出来的子进程,A 和 B 之间不存在父子关系,它俩的父进程都是 shell。
所以说,在 shell 里通过「|」匿名管道将多个命令连接在一起,实际上也就是创建了多个子进程,那么在我们编写 shell 脚本时,能使用一个管道搞定的事情,就不要多用一个管道,这样可以减少创建子进程的系统开销。
66. 消息队列
消息队列克服了管道通信的数据是无格式的字节流的问题,消息队列实际上是保存在内核的「消息链表」,消息队列的消息体是可以用户自定义的数据类型,发送数据时,会被分成一个一个独立的消息体,当然接收数据时,也要与发送方发送的消息体的数据类型保持一致,这样才能保证读取的数据是正确的。消息队列通信的速度不是最及时的,毕竟每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。
相比于 FIFO,消息队列具有以下优点:
- 消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
- 避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;
- 读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收。
原文地址:https://blog.csdn.net/Newin2020/article/details/143759020
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!