1. 父子进程使用文件进行通信
先打开一个文件,然后fork出子进程,父进程和子进程都拥有这个文件描述符。父进程向该文件中写一句话,然后关闭文件描述符。然后过了一秒后子进程醒了,子进程先把文件指针移到文件的初始位置,然后读文件并打印输出,最后关闭文件描述符。
示意图:
执行结果:
2. 父进程fork三个子进程例子
段错误:
执行结果:
解释:前两个子进程是正常退出的,最后一个子进程是发生了段错误,于是系统会向该子进程发信号11杀死该子进程。所以结果如上图。
3. waitpid函数
注:如果子进程被创建出来之后,通过某种操作被送到了其他进程组中,那么该子进程就不和父进程在同一个进程组了,参数需要用pid<0,将该子进程的pid加个负号。(pid参数大于0和等于-1的这两种比较常用)
例:pid参数为-1,非阻塞。
解释:当wpid等于0时,说明子进程处于运行状态,那么continue。
4. ipc的概念
5. 管道相关的概念
6. pipe函数的使用
返回值:成功为0,失败为-1。
例:
执行结果:
7. 有血缘关系的进程间通信fork的位置
fork位置应该在创建管道之后,这样父进程和子进程就都使用同一个管道。
8. 使用匹配父子进程间通信练习思路
ps aux默认是写到终端的,所以我们需要用dup2,这样在文件描述符重定向之后,ps aux就会写到管道的“写”端了。同理,grep bash默认是从终端读的,所以我们需要用dup2,这样在文件描述符重定向之后,grep bash就会从管道的“读”端去读了。
管道的内部实现是队列,所以数据只能读一次。当子进程往管道中写数据时,为了防止父进程也读、子进程也读的情况,要在子进程中关闭管道的读端,这样就只是子进程在写,父进程在读了;当父进程从管道中读数据时,为了防止父进程也写,子进程也写的情况,要在父进程中关闭管道的写端,这样就只是子进程在写,父进程在读了。
9. 父子进程通信代码实现 ps aux | grep bash
执行结果:
注:1. 上面是父进程写,子进程读。如果我们还需要进行父进程读,子进程写的话,那么我们就需要再创建一根管道。
2. 如果写操作的进程不关闭读端,读操作的进程不关闭写端,那么会造成阻塞,grep读不到数据一直在那里等,如下:
10. 兄弟进程间通信
父进程中需要关闭管道的读写两端。子进程1中需要关闭管道的读端,子进程2中需要关闭管道的写端。
例:
执行结果:
11. 管道的读写行为
12. 验证管道缓冲区大小
例:
执行结果:
13. 设置管道的非阻塞属性
上面的三行紫色代码即可完成设置管道的非阻塞属性。
14. fifo的创建
fifo文件大小为0,里面不存数据,数据存在内核的缓冲区里面。只要有fifo文件,就会和内核缓冲区做一个映射,这是操作系统行为。
其中pathname是fifo文件的名字,mode是设置文件权限的参数。最终真正的权限是我们设置的参数再与umask取反的按位与:
15. fifo进行没有血缘关系的进程间通信
先创建fifo文件,名字是myfifo,然后执行a.c的进程和执行b.c的进程之间进行通信:
管道默认有阻塞属性,所以当写进程还没有写数据时,读进程会阻塞在那里等待。当管道中有数据了之后,读进程就开始读。
16. mmap函数参数讲解
(1)mmap函数
注:映射区的大小为4k的整数倍,所以如果参数设置为100字节,会发现映射区大小为4k。
(2)munmap函数
17. 使用mmap读取磁盘文件内容