管道,你造吗??

前言:

进程间通讯方式有:消息队列、管道、信号量、共享内存、信号(信号值)、套接字(socket)。

管道:在多个进程之间传递数据的通道。分为无名管道和有名管道,他们都是一种半双工通讯方式。这种方式效率低,进程操作文       件相互独立,不能实现同步通讯。

一、有名管道

1. 定义:  在磁盘上会存在一个管道文件,但在进程通讯时,数据不会保存到磁盘上。(管道文件并不会占用磁盘的block空间)

 2.相关操作:

  •     创建:  命令方式: mkfifo  filename         函数方式:int mkfifo(char *filename,mode_t mode);
  •     打开管道文件:int open (char *filename,int flag);
  •     写入数据:int  write(int flag,void *buff,size_t size);
  •    读数据:int read(int flag,void *buff,size_t size);
  •     关闭管道文件:int close(int fd);

eg: 进程A将用户输入的数据传递给进程B,B进程将数据显示出来。

       

   有名管道操作时,创建管道对应的内存空间是在有读有写时创建;

   打开管道文件时,open如果只以只读/只写的方式打开,则会进入阻塞状态,知道另一个进程以只读/只写被打开;

   如果读端或写端关闭,则对应的写端/读端也会直接退出;

   所以,综上所述要想通过管道通讯,必须保证有读有写。

  管道文件仅仅缓存发送的数据,并不能区分数据的分割点! 写了两次,一次退出。——>子节点

  •    一次接收的数据长度可能不等于一次发送的数据长度。
  •   如果有多个读端,写端发送的数据具体有那个数据读取,由系统当前的运行状态决定。

二、无名管道

    1.定义:没有管道文件,借助于父子进程之间共享fork之前打开的文件描述符,父子进程通过相同的文件描述符操作同一块内存空间。父子进程fork之前打开管道文件,如果父进程写入数据,则在子进程写入数据时,是接着父进程操作位置继续写入。

    2.相关操作

      创建和打开: int pipe(fd[2]); //表示有两个文件描述符。fd[0]指向管道的读端,fd[1]指向管道的写端。

                  父进程关闭读端,子进程关闭写端。同样,父进程关闭写端,子进程关闭读端。

                   在管道文件正式通讯前,应该关闭一对读、写端。因为它是一种半双工通讯方式

  3.有名管道和无名管道的区别:

  •      有名管道用于任意两个进程之间,而无名管道只能用于父子进程之间
  •      有名管道通讯是双向的,任意一端可读可写。但在同一时间段,只能一端读一端写;无名管道不能再网络间通讯,单              向,只能一端读一端写。

三、有关管道的思考

    1.写入管道的数据会乱序吗??

       管道是个流式的,依次写入,依次顺序读取。不会乱序,但多线程中如果两个线程 同时写入,数据可能会交替在一起。  

   2.管道为什么是个半双工模式???

      linux系统下一个命令只能实现一个功能。如果想要实现较复杂的任务,就需要多个进程共同完成。将第一个进程处理结果传递给第二个进程,然后依次传递,这就好像一条完整的生产链。我们需要做的就是把数据传递下去,所以为半双工模式。也可以设置为全双工模式,但这样就麻烦多了。如果使用全双工模式建议使用双向管道(socketpair),但它的本质是两个套接字。

    

附加:

  同步:需要内核通知机制(信号 中断)支持。当调用一个可能阻塞的函数时,函数立即返回,进程继续执行,当收到通知机制时,才处理相应事件;

  异步:程序完全按照代码的顺序执行,如果调用一个阻塞函数,进程一直等待该函数返回。

  父子进程fork之前共享文件描述符以及地址偏移量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值