面试官:能简单聊聊进程间的通信方式吗?
派大星:可以的,主要方式为:管道、命名管道、消息队列、共享内存。
面试官:可以简单介绍一下这些通信方式吗?
派大星:好的。首先说一下:
- 管道(pipe):
unix操作系统里面,有一个fork操作
,可以创建进程的子进程,或者说是复制一个进程完全一样的子进程,共享代码空间,但是各自有独立的数据空间,不过子进程的数据空间是拷贝父进程的数据空间的。
管道机制要求的是两个进程之间是有血缘关系的。就比如fork出来的父子进程
。
Linux操作系统里面,管道用来缓存要在进程间传输的数据,管道是一个固定大小的缓冲区,大小为4kb
。管道中的数据一旦被读取出来,就不在管道里面了。但是如果管道满了,那么写管道的操作就阻塞了,直到别人读了管道的数据;反之如果管道是空的,那么读操作的管道就阻塞了。管道一边连着一个进程的输出,一遍连着进程的输入,然后就一个进程写数据另外一个进程读数据、如果两个进程都没了管道也就没了。管道是半双工的
,就是数据只能流向一个方向,就比如说你架设一个管道,只能一个进程写,一个进程读。
Linux里面对管道的实现是使用了两个文件,指向了一个VFS(虚拟文件系统)的索引节点node,然后VFS索引节点指向一个物理页面,接着一个进程通过自己关联的那个文件写数据,另外一个进程通过自己关联的那个文件读数据。
其次聊一下:
- 命名管道(FIFO)
管道的通信要求必须是父子关系的进程间通信,这样就受到了限制。所以可以用命令管道来解决这个问题。
之前的管道是没有名字的,所以必须是有父子关系的进程才可以使用。但是命名管道是有名字的。这个命名管道相当于是有一个名字的文件,是有路径的。所以没有血缘关系的进程都可以通过这个命名管道来进行通信,名字在文件系统上,数据在内存里。其它的和管道一样:一个进程写,一个进程读。也是半双工
。数据只能单向滚动
然后聊聊:
- 消息队列
Linux的消息队列可以认为是一个链表结构。Linux内核有一个msgque链表,这个链表里的每个指针指向一个msgid_ds结构,这个结构就描述了一个消息队列。然后进程间就通过这个消息队列即可完成通信。益阳市写入数据和消费数据,消费队列的好处是对每个消息可以指定类型,消费的时候就消费指定类型的消息即可。功能也相对比较多一些。
最后说一下:
- 共享内存
一块物理内存被映射到两个进程的进程地址空间,所以进程之间互相都可以立即看到对方在共享内存里做出的修改。有利有弊由于其是共享内存,所以需要锁来保证同步,这里就涉及了Linux底层的一些东西了。不做展开,可自行了解。
面试官:不错,你知道线程见如何切换吗?简单聊聊?
派大星:这个了解一些。简单的讲就是一个进程的多个线程间切换的时候就涉及到了上下文切换。简单来说就是有一个时间片算法,CPU给每个线程一个时间片来执行,时间片结束之后,就保存当前线程的状态然后切换到下一个线程去执行。这就是所谓多线程并发执行的原理。就是多个线程来来回回的切换。每个线程就一个时间片里执行。底层原理可自行去了解哈。