Linux系统编程(2)

1. 父子进程使用文件进行通信

Linux系统编程(2)

Linux系统编程(2)

先打开一个文件,然后fork出子进程,父进程和子进程都拥有这个文件描述符。父进程向该文件中写一句话,然后关闭文件描述符。然后过了一秒后子进程醒了,子进程先把文件指针移到文件的初始位置,然后读文件并打印输出,最后关闭文件描述符。

示意图:

Linux系统编程(2)

执行结果:

Linux系统编程(2)

2. 父进程fork三个子进程例子

Linux系统编程(2)

段错误:

Linux系统编程(2)

Linux系统编程(2)

 Linux系统编程(2)

执行结果:

Linux系统编程(2)

解释:前两个子进程是正常退出的,最后一个子进程是发生了段错误,于是系统会向该子进程发信号11杀死该子进程。所以结果如上图。

3. waitpid函数

Linux系统编程(2)

        Linux系统编程(2)

注:如果子进程被创建出来之后,通过某种操作被送到了其他进程组中,那么该子进程就不和父进程在同一个进程组了,参数需要用pid<0,将该子进程的pid加个负号。(pid参数大于0和等于-1的这两种比较常用)

例:pid参数为-1,非阻塞。

 Linux系统编程(2)

Linux系统编程(2)

解释:当wpid等于0时,说明子进程处于运行状态,那么continue。

4. ipc的概念

Linux系统编程(2)

5. 管道相关的概念

Linux系统编程(2)

 Linux系统编程(2)

Linux系统编程(2)

6. pipe函数的使用

Linux系统编程(2)

返回值:成功为0,失败为-1。

例:

Linux系统编程(2)

执行结果:

Linux系统编程(2)

7. 有血缘关系的进程间通信fork的位置

Linux系统编程(2)

fork位置应该在创建管道之后,这样父进程和子进程就都使用同一个管道。

8. 使用匹配父子进程间通信练习思路

Linux系统编程(2)

ps aux默认是写到终端的,所以我们需要用dup2,这样在文件描述符重定向之后,ps aux就会写到管道的“写”端了。同理,grep bash默认是从终端读的,所以我们需要用dup2,这样在文件描述符重定向之后,grep bash就会从管道的“读”端去读了。

Linux系统编程(2)

管道的内部实现是队列,所以数据只能读一次。当子进程往管道中写数据时,为了防止父进程也读、子进程也读的情况,要在子进程中关闭管道的读端,这样就只是子进程在写,父进程在读了;当父进程从管道中读数据时,为了防止父进程也写,子进程也写的情况,要在父进程中关闭管道的写端,这样就只是子进程在写,父进程在读了。

Linux系统编程(2)

9. 父子进程通信代码实现 ps aux | grep bash

Linux系统编程(2)

       Linux系统编程(2)

 Linux系统编程(2)

执行结果:

Linux系统编程(2)

注:1. 上面是父进程写,子进程读。如果我们还需要进行父进程读,子进程写的话,那么我们就需要再创建一根管道。

       2. 如果写操作的进程不关闭读端,读操作的进程不关闭写端,那么会造成阻塞,grep读不到数据一直在那里等,如下:

Linux系统编程(2)

10. 兄弟进程间通信

Linux系统编程(2)

父进程中需要关闭管道的读写两端。子进程1中需要关闭管道的读端,子进程2中需要关闭管道的写端。

例:

 Linux系统编程(2)

  Linux系统编程(2)

  Linux系统编程(2)

执行结果:

Linux系统编程(2)

11. 管道的读写行为

Linux系统编程(2)

Linux系统编程(2)

12. 验证管道缓冲区大小

Linux系统编程(2)

例:

Linux系统编程(2)

执行结果:

Linux系统编程(2)

13. 设置管道的非阻塞属性

Linux系统编程(2)

上面的三行紫色代码即可完成设置管道的非阻塞属性。

14. fifo的创建

Linux系统编程(2)

fifo文件大小为0,里面不存数据,数据存在内核的缓冲区里面。只要有fifo文件,就会和内核缓冲区做一个映射,这是操作系统行为。

Linux系统编程(2)

Linux系统编程(2)

Linux系统编程(2)

其中pathname是fifo文件的名字,mode是设置文件权限的参数。最终真正的权限是我们设置的参数再与umask取反的按位与:

Linux系统编程(2)

15. fifo进行没有血缘关系的进程间通信

先创建fifo文件,名字是myfifo,然后执行a.c的进程和执行b.c的进程之间进行通信:

Linux系统编程(2)

管道默认有阻塞属性,所以当写进程还没有写数据时,读进程会阻塞在那里等待。当管道中有数据了之后,读进程就开始读。

16. mmap函数参数讲解

(1)mmap函数

Linux系统编程(2)

Linux系统编程(2)

   Linux系统编程(2)

       Linux系统编程(2)    

  Linux系统编程(2)

注:映射区的大小为4k的整数倍,所以如果参数设置为100字节,会发现映射区大小为4k。

(2)munmap函数

Linux系统编程(2)

17. 使用mmap读取磁盘文件内容

Linux系统编程(2)