zoukankan      html  css  js  c++  java
  • 进程间通信之管道

      

       管道是linux的一种通信方式,一种两个进程间进行单向通信的机制,它提供了简单的流控制机制,系统提供了pipe生成一个管道并返回两个描述符,一 个用来读管道,一个用来写管道,因此它们可以共享访问文件,这样每个管道就可以有很多个读进程和写进程,然而实际上进程不知道它正在读或写的是一个管道, 它有以下局限性:

      由于管道传递数据的单向性,决定其使用的局限性:数据的单向流动;有亲缘关系的进程间的通信;没有名字;缓冲区大小受限制(传送的是无格式的字节流)

         管道就是一个存在于内存的特殊文件,进程就是通过读写该文件进行通信的(内存中的某个页面作为数据缓冲区)

         如果要建立两个进程的数据通路,首先父进程应调用pipe创建管道,接着调用fork,由于子进程自动继承父进程的数据段,便可实现父子进程同时拥有管 道 的操作权,如下图(a),但为了维护管道,比如想要一个父进程到子进程的数据通道时,在父进程中关闭读出端,子进程中关闭管道的写入端,图(b)。

    管道的创建
        Linux下创建管道可以通过函数pipe来完成。该函数如果调用成功返回0,并且数组中将包含两个新的文件描述符:如果有错误发生,返回-1。该函数原型如下:
    #include <unistd.h>
    int pipe(int fd[2]);
        管道两端可分别用描述符fd[0]以及fd[1]来描述。需要注意的是,管道两端的任务是固定的,一端只能用于读,由描述符fd[0]表示,称其为管道读 端;另一端只能用于写,由描述符fd[1]来表示,称其为管道写端。如果试图从管道写端读数据,或者向管道读端写数据都将导致出错。
        管道是一种文件,因此对文件操作的I/O函数都可以用于管道,如read(),write()等。
        注意:管道是一旦创建成功,就可以作为一般的文件来使用,对一般文件进行操作的I/O函数也适用于管道,如:
        管道的一般用法是,进程在使用fork函数创建子进程前先创建一个管道,该管道用于在父子进程间通信,然后创建子进程,之后你进程关闭管道的读端,子进程 关闭管道的写端。父进程负责向管道写数据而子进程负责读数据。当然父进程可以关闭管道的写端而子进程关闭管道的读端。这样管道就可以用于父子进程间的通 信,也可用于兄弟进程间的通信。下面介绍进程是如何通过管道来读写数据的。

    管道关闭

            管道关闭只需将这两个文件描述符关闭即可,可以使用普通的close函数进行关闭。


    从管道中读数据
        如果某进程要读取管道中的数据,那么该进程应当关闭fd1,同时向管道写数据的进程应当关闭fd0。因为管道只能用于具有亲缘关系的进程间的通信,在各进程进行通信时,它们共享文件描述符。在使用前,应及时地关闭不需要的管道的另一端,以避免意外错误的发生。
        进程在管道的读端读数据时,如果管道的写端不存在,则读进程认为已经读到了数据的末尾,该函数返回读出的字节数为0;管道的写端不存在,则读取的字节数大 于PIPE_BUF,则返回管道中现有的所有数据;如果请求的字节数不大于PIPE_BUF,则返回管道中现有的所有数据(此时,管道中数据量小于请求的 数据量),或者返回请求的字节数(此时,管道中数据量大于等于请求的数据量)。
        注意:PIPE_BUF在include/linux/limits.h中定义,不同的内核版本可能会有所不同。


    向管道中写数据
        如果某进程希望向管道中写入数据,那么该进程应该关闭fd0文件描述符,同时管道另一端的进程关闭fd1。向管道中写入数据时,Linux不保证写入的原 子性(原子性是指操作在任何时候都不能被任何原因所打断,操作要么不做要么就一定完成)。管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读 进程不读走管道缓冲区中的数据,那么写操作将一直被阻塞等待。
        在写管道时,如果要求写的字节数小于等于PIPE_BUF,则多个进程对同一管道的写操作不会交错进行。但是,如果有多个进程同时写一个管道,而且某些进程要求写的字节数超过PIPE_BUF所能容纳时,则多个写操作的数据可能会交错。
        注意:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIGPIPE信号。应用程序可以处理也可以忽略该信号,如果忽略该信号或者捕捉该信号并从其处理程序返回,则write出错,错误码为EPIPE。

  • 相关阅读:
    Android 开发 深入理解Handler、Looper、Messagequeue 转载
    Android 开发 Handler的基本使用
    Java 学习 注解
    Android 开发 AlarmManager 定时器
    Android 开发 框架系列 百度语音合成
    Android 开发 框架系列 Google的ORM框架 Room
    Android 开发 VectorDrawable 矢量图 (三)矢量图动画
    Android 开发 VectorDrawable 矢量图 (二)了解矢量图属性与绘制
    Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图
    Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID
  • 原文地址:https://www.cnblogs.com/lihuidashen/p/3466656.html
Copyright © 2011-2022 走看看