Linux系统编程3——进程间通信

文章目录

  • 前言
  • 一、什么是进程间通信
  • 二、进程间通信方式
  • 三、管道
    • 1、管道的原理
    • 2、管道的局限性
    • 3、创建管道函数——pipe
    • 4、父子进程使用管道通信
        • 使用pipe完成ps aux | grep bash操作
    • 5、管道的读写行为
        • 读操作
        • 写操作
    • 6、如何设置管道为非阻塞
    • 7、查看管道缓冲区大小
  • 四、FIFO
    • 1、创建管道
    • 2、使用FIFO完成两个进程通信
  • 五、内存映射区
    • 1、内存映射区介绍
    • 2、mmap函数
    • 3、munmap函数
    • 4、mmap函数注意事项
    • 5、mmap函数参数总结
    • 6、匿名映射
  • 六、信
    • 1、信 的概念
    • 2、信 的机制
      • 2.1、信 的状态
      • 2.2、信 的处理方式
      • 2.3、信 的特质
      • 2.4、阻塞信 集和未决信 集
      • 2.5、信 的四要素
      • 3、信 相关函数
        • 3.1、signal函数
        • 3.2、kill函数/命令
        • 3.3、abort函数
        • 3.4、raise函数
        • 3.5、alarm函数
      • 3.6、setitimer函数
    • 4、信 集
      • 4.1、未决信 集和阻塞信 集的关系
      • 4.2、信 集相关函数
        • 4.2.1、sigemptyset
        • 4.2.2、sigfillset
        • 4.2.3、sigaddset
        • 4.2.4、sigdelset
        • 4.2.5、sigismember
        • 4.2.6、sigprocmask
        • 4.2.7、sigpending函数
    • 5、信 捕捉函数
      • 5.1、sigaction函数
      • 5.2、内核实现信 捕捉的过程
    • 6、SIGCHLD信
      • 6.1、产生SIGCHLD信 的条件
      • 6.2、SIGCHLD信 的作用
  • 七、本地socket通信
    • 1、socket函数
    • 2、bind函数

前言

一、什么是进程间通信

Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。

  • 管道的本质是一块内核缓冲区
  • 有两个文件描述符引用,一个表示读端,一个表示写断
  • 规定数据从管道的写断流入管道,从读断流出
  • 当两个进程都终结的时候,管道也自动消失
  • 管道的读断和写端默认是阻塞的

1、管道的原理

管道的实质是内核缓冲区,内部使用环形队列实现,默认缓冲区大小为4K,可以使用命令 获取大小。实际操作过程中缓冲区会根据数据压力做适当调整。

2、管道的局限性

  1. 数据一旦被读走,便不在管道中存在,不可反复读取
  2. 数据只能在一个方向上流动,若要实现双向流动,必须使用两个管道(半双工)
  3. 只能在有血缘关系的进程间使用管道(父子进程等)

3、创建管道函数——pipe

函数调用成功返回读端和写端的文件描述符,其中fd[0]是读端, fd[1]是写端,向管道读写数据是通过使用这两个文件描述符进行的,读写管道的实质是操作内核缓冲区。
管道创建成功以后,创建该管道的进程(父进程)同时掌握着管道的读端和写端。如何实现父子进程间通信呢/p>

4、父子进程使用管道通信

一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在血缘关系,这里的血缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。
步骤:

  1. 父进程调用pipe()函数,得到两个文件描述符fd[0]和fd[1],分别指向管道的读端和写断
  2. 父进程调用fork创建子进程,子进程也有两个文件描述符指向同一管道
  3. 父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出,这样就实现了父子进程间通信。

使用pipe完成ps aux | grep bash操作

读操作

  • 有数据
    read读正常,返回读出的字节数
  • 无数据
    写端全部关闭:read解除阻塞,返回0,相当于文件读到了尾部
    写端没有全部关闭:read阻塞

写操作

  • 读端全部关闭
    管道破裂,进程终止,内核给当前进程发SIGPIPE信
  • 读端没全部关闭
    缓冲区写满了:write阻塞
    缓冲区没有满:继续write

6、如何设置管道为非阻塞

默认情况下,管道的读写两端都是阻塞的,若要设置读或者写端为非阻塞,则可参考下列三个步骤进行:

  1. 第1步: int flags = fcntl(fd[0], F_GETFL, 0);
  2. 第2步: flag |= O_NONBLOCK;
  3. 第3步: fcntl(fd[0], F_SETFL, flags);

若是读端设置为非阻塞:

  • 写端没有关闭,管道中没有数据可读,则read返回-1
  • 写端没有关闭,管道中有数据可读,则read返回实际读到的字节数
  • 写端已经关闭,管道中有数据可读,则read返回实际读到的字节数
  • 写端已经关闭,管道中没有数据可读,则read返回0

7、查看管道缓冲区大小

命令

函数

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年11月3日
下一篇 2022年11月3日

相关推荐