进程IPC之PIPE(一)

1. PIPE

#include <unistd.h>
int pipe(int fd[2]);
Returns: 0 if OK, −1 on error

Pipe半双工且只能用于具有共同父进程的进程间通信, 当其返回的时候设置fd[0]为读端口,fd[1]为写端口,且fd[1]fd[0]相连。如下图所示:
这里写图片描述

其中Pipe的使用关键只要记住下面这个图:
这里写图片描述

pipe的一端被关闭的时候,需要记住以下两个准则:

  • If we read from a pipe whose write end has been closed, read returns 0 to indicate an end of file after all the data has been read.
  • If we write to a pipe whose read end has been closed, the signal SIGPIPE is generated. If we either ignore the signal or catch it and return from the signal handler, write returns −1 with errno set to EPIPE
>**NOTE : A write of PIPE_BUF bytes or less will not be interleaved with the writes from other processes to the same pipe (or FIFO). But if multiple processes are writing to a pipe (or FIFO), and if we write more than PIPE_BUF bytes, the data might be interleaved with the data from the other writers.**

2. popen and pclose Functions

#include <stdio.h>
FILE *popen(const char *cmdstring, const char *type);
Returns: file pointer if OK, NULL on error
int pclose(FILE *fp);
Returns: termination status of cmdstring, or −1 on error

这两个函数自动做了很多操作:创建pipe,fork一个子进程并关闭不用的端口,执行shell去运行一个命令,并等待命令结束。最简单记住的方式:

One way to remember the final argument to popen is to remember that, like fopen, the returned file pointer is readable if type is “r” or writable if type is “w”.

pclose关闭标准IO流,等待popen中的cmdstring结束,并返回子shell的结束信息,如果子shell未成功执行cmdstring则返回127注意:popen产生的子进程exec的命令为sh -c cmdstring POSIX.1做了以下两点要求:

  • POSIX.1 requires that popen close any streams that are still open in the child from previous calls to popen.
  • Note that if the application calls waitpid and obtains the exit status of the child created by popen, we will call waitpid when the application calls pclose, find that the child no longer exists, and return −1 with errno set to ECHILD. This is the behavior required by POSIX.1 in this situation.

3. Coprocesses

A coprocess normally runs in the background from a shell, and its standard input and standard output are connected to another program using a pipe. Whereas popen gives us a one-way pipe to the standard input or from the standard output of another process, with a coprocess we have two one-way pipes to the other process: one to its standard input and one from its standard output.

猜想:如果想让Coprocess处于后台进程组,只要保证其不和Control Terminal有关联就行。这里题目一验证
  如果对于Pipe调用标准IO函数,其分配的buffer区域为full buffer,所以在某些场合,比如需要读取用户终端输入的时候,如果不及时flush相应的缓冲区,可能程序并不能很好的工作。如果不能修改Coprocess的源码,就需要通过使用pseudo terminals来使Coprocess中相应的标准IO函数认为自己连接到了一个终端设备。

4. FIFOs

#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
Both return: 0 if OK,1 on error

基于PIPE进行进程通信的原理,其只能被具有一定关系的进程通信。(比如父子,爷孙关系)往深了理解就是因为pipe利用了forkfd的继承特性,而fifo可以被不相干的进程用来进行通信。创建FIFO和创建一个文件很像,mkfifomkfifoat的用法与openopenat相似。
  创建之后的FIFO,被打开之后可以对其使用一系列的IO函数,在命令行中可以使用一个mkfifo命令创建FIFO,并且可以对其使用重定向符。当用open打开一个FIFO时,指定O_NONBLOCK是否将会有以下的影响:

  • In the normal case (without O_NONBLOCK), an open for read-only blocks until some other process opens the FIFO for writing. Similarly, an open for writeonly blocks until some other process opens the FIFO for reading.
  • If O_NONBLOCK is specified, an open for read-only returns immediately. But an open for write-only returns −1 with errno set to ENXIO if no process has the FIFO open for reading

**以上两点确实与文件IO差别甚大,**打开一个常规文件是不会阻塞的,但是打开fifo将会遇到上面引用所述的情形。向一个FIFO写入数据而该FIFO没有被其他的进程以读的方式打开,SIGPIPE信号就会产生;在关闭FIFO之后,别的进程对其进行读操作会遇到文件末尾,前提FIFO中的数据已被读完。(这里需要题目二验证一下FIFO的两个重要作用:

  • FIFOs are used by shell commands to pass data from one shell pipeline to another without creating intermediate temporary files.
  • FIFOs are used as rendezvous points in client–server applications to pass data between the clients and the servers
>**NOTE : As with pipes, the constant PIPE_BUF specifies the maximum amount of data that can be written atomically to a FIFO.**

5. 实验部分

题目一:

验证是否如果想让Coprocess处于后台进程组,只要保证其不和Control Terminal有关联就行。

题目二:
  • 使用fifo实现Coprocess
  • 对于读端来说,关闭fifo的写端是否立即产生文件末尾?
题目三:

Explain how select and poll handle an input descriptor that is a pipe, when the pipe is closed by the writer. To determine the answer, write two small test programs: one using select and one using poll.
Redo this exercise, looking at an output descriptor that is a pipe, when the read end is closed.

>**NOTE : 本篇实验颇多,重点将集中于实验部分。以上论述如有疑问,请及时指正。**
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值