进程间通信:管道

进程间通信(InterProcessComnuication)

      进程间通信:不同进程间传播交换信息。

  • 进程间为什么要沟通交流?

因为进程的独立性,而在实际工作中往往会出现在一个系统中好几个进程协同工作,那么这进程就需要交流沟通完成协作。也因为进程的独立性,因此进程间的沟通交流将变得困难,复杂。因此就产生了各种进程间通信方式,来解决如何进行进程间通信的问题。

  • 进程间通信的目的:
  • 数据传输:一个进程需要将它的数据发送给另一个进程。
  • 资源共享:多个进程之间共享同样资源。
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件(如子进程终止时要通知父进程获取子进程退出信息)。
  • 进程控制:有些进程希望完全控制另一个进程的执行,此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
  • 进程间通信分类:
  • 管道 // 最早的通信方式:
  1. 匿名管道pipe
  2. 命名管道
  • 消息队列
  • 共享内存
  • 信号量
  • 互斥量
  • 条件变量
  • 读写锁
  • Socket 和 Stream // 用于不同主机上两个进程的IPC(网络模块内容,在此不具体介绍)

 

管道:

      作用:传输数据资源

      相当于进程间通信的媒介,本质上是内核的一块缓冲区

      Linux下一切皆文件,操作系统为管道提供的操作方法:文件操作

 

      管道符:

例如: ps -ef | grep ssh // 管道符: | 左边进程的结果交由右边进程来处理

      特性:

半双工,单向通信。

      管道读写规则:

  • 管道无数据:读取

        如果描述符是默认的阻塞属性,这时读取将会阻塞挂起等待,直到管道有数据;

        如果描述符被设置为非阻塞属性,读取操作将不具备条件,直接报错返回 EAGIN

  • 管道数据满了:写入

        如果描述符是默认的阻塞属性,写入操作将会阻塞挂起等待,直到有数据被取走;

        如果描述符被设置为非阻塞属性,写入操作将不具备条件,直接报错返回 EAGIN

  • 当写入端都被关闭:

        这时候如果读取数据,读取完管道中的数据,然后返回0

  • 当读取端都被关闭:

        这时候如果写入数据,则会触发异常,操作系统会给进程发送SIGPIPE信号(13号信号),进程收到后会退出。

  • 当写入的数据量不大于PIPE_BUF时:

        Linux将保证写入的原子性。

  • 当写入的数据量大于PIPE_BUF:

        Liunx不再保证写入原子操作。

 

  • 匿名管道:

       原理:

           管道借助内核缓冲区(4k大小),使用环形队列机制实现。

 

       匿名管道特性:

  1.  创建的缓冲区是没有名字的,仅用于具有亲缘关系的进程间通信;
  2.  管道是半双工单项通信
  3.  管道的生命周期随进程(打开管道后,直到进程退出,管道释放);
  4.  管道是面向字节流传输数据的; // 面向字节流:数据无规则,没有明显边界,收发数据灵活。
  5.  自带同步与互斥。
临界资源:都能访问到的共享资源

临界区:对临界资源进行操作的代码

同步:访问的可控时序性

互斥:对临界资源同一时间的唯一访问性(保护临界资源安全)

 

 

       匿名管道创建:

#include <unistd.h> int pipe(int pipefd[2]);
  • pidefd:用于接收匿名管道创建成功之后返回的两个描述符
  • pipefd[0]:用于从管道读取数据
  • pipefd[1]:用于从管道写入数据
  • 返回值: 成功:0; 失败:-1.

     

  • 命名管道:

      特性:

  1. 可以应用于同一主机上任意进程间通信;
  2. 文件系统可见,但是FIFO在磁盘上没有数据块,仅仅用来标识内核中一条通道,是一个特殊类型管道文件。

      创建:

         1. 命令创建:

mkfifo pipe_filename

         2. 代码创建:

#include <sys/types.h> 
#include <sys/stat.h> 

int mkfifo(const char *pathname, mode_t mode);
  • pathname:管道文件的路径名
  • mode: 管道文件的权限
  • 返回值:成功:0 失败: -1

说明:

   常见的文件I/O函数(read、write、close)都可以用于FIFO;

   一个命名管道打开之后,则所有特性和匿名管道完全相同。

 

       命名管道打开规则:

1. 如果以只读打开命名管道,那么open函数将阻塞的等待,直到有其他进程以写的方式打开这个命名管道;

2. 如果以只写打开命名管道,那么open函数将阻塞的等待,直到有其他进程以读的方式打开这个命名管道;

3. 如果以读写打开命名管道,则不会阻塞。

      为什么命名管道有特性而匿名管道没有?

    由于命名管道是可见于文件系统,需要用户自己打开文件;

    匿名管道是不可见于文件系统,所需操作只用pipe就能完成,打开的整个过程是在内部完成的。它在创建之后就直接打开返回描述符了。

 

查看管道缓冲区大小方式:

命令:

ulimit -a

函数:

#include <unistd.h>

long fpathconf(int fd, int name); // 成功返回缓冲区大小;失败返回-1

 

小结:

  管道较于信号、套接字等其他IPC来说操作简单,但是只能单向通信(可以通过两个管道实现双向通信)。

  匿名管道只能用于有亲缘关系的进程间通信,而命名管道可以在任意两进程间通信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值