UNP(卷2:进程间通信)—— 第4章:管道和FIFO


管道

由pipe创建,提供一个单向的数据流。

#include <unistd.h>

int pipe(int fd[2]);
                                     // 返回:成功则为0,出错则为-1
该函数返回两个文件描述符 fd[0] 和 fd[1] 。前者打开来读,后者打开来写

所有管道都是半双工的,即单向数据流。

全双工管道

某些系统提供全双工管道:

1、SVR4的pipe函数。


2、socketpair函数。

/* socketpair - create a pair of connected sockets */

#include <sys/socket.h>

int socketpair(int domain, int type, int protocol, int socket_vector[2]);
                                                                           // 返回:成功则为0,出错则为-1

popen 和 pclose 函数

#include <stdio.h>

FILE *popen(const char *command, const char *type);
                                                    // 返回:若成功则为文件指针,若出错则为NULL

int pclose(FILE *stream);
                                                    // 返回:若成功则为shell的终止状态,若出错则为-1

popen 函数,它创建一个管道并启动另外一个进程,该进程要么从该管道读出标准输入,要么往该管道写入标准输出。

command是一个shell命令行,

type:

(1)type为 r ,调用进程读进command的标准输出。

(2)type为 w,调用进程写进command的标准输入。

pclose函数关闭有popen创建的标准I/O流,等待其中的命令终止,然后返回shell的终止状态。


FIFO

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

int mkfifo(const char *pathname, mode_t mode);
                                                      // 返回:成功则为0,出错则为-1

pathname是一个路径名。FIFO的名字。

mode参数指定文件权限位。

在创建出一个FIFO后,它必须或者打开来读,或者打开来写。不能打开来既读又写,因为它是半双工的。


首先,一个描述符能以两种方式设置成非阻塞。

(1)调用open时可指定O_NONBLOCK标志。

(2)如果一个描述符已经打开,那么可以调用fcntl以启用O_NONBLOCK标志。

因为管道没有open调用,在pipe调用中没法指定O_NONBLOCK标志,所以管道必须使用fcntl函数来设置。



下面是关于管道或FIFO的读出与写入的若干额外规则。

(1)如果请求读出的数据量多于管道或FIFO中当前可用数据量,那么只返回这些可用的数据。


(2)如果请求写入的数据的字节数小于或等于PIPE_BUF(一个Posix限制值,可以通过getconf命令查看PIPE_BUF的大小),那么write操作保证的原子的。这意味着,如果有两个进程差不多同时往同一个管道或FIFO写,那么或者先写入来自第一个进程的所有数据,再写入来自第二个进程的所有数据,或者颠倒过来。系统不会互相混杂来自这两个进程的数据。然而,如果请求写入的数据的字节数大于PIPE_BUF,那么write操作不能保证是原子的。


(3)O_NONBLOCK标志的设置对write操作的原子性没有影响。原子性完全是由所请求字节数是否小于等于PIPE_BUF决定的。然而当一个管道或FIFO设置成非阻塞时,来自write的返回值取决于待写的字节数以及该管道或FIFO中当前可用空间的大小。

写入的字节数小于等于PIPE_BUF:

a.如果该管道或FIFO中有足以存放所请求字节数的空间,那么所有数据字节都写入。

b.如果该管道或FIFO中没有足以存放所请求字节数的空间,那么立即返回一个EAGAIN错误。

写入的字节数大于PIPE_BUF:

a.如果该管道或FIFO中至少有1字节空间,那么内核写入该管道或FIFO能容纳数目的数据字节,该数目同时作为来自write的返回值。

b.如果该管道或FIFO已满,那么立即返回一个EAGAIN错误。


(4)如果向一个没有为读打开着的管道或FIFO写入,那么内核将产生一个SIGPIPE信号;

a.如果调用进程既没有捕获也没有忽略该SIGPIPE信号,所采取的默认行为就是终止该进程。

b.如果调用进程忽略了该SIGPIPE信号,或者捕获了该信号并从其信号处理程序中返回,那么write返回一个EPIPE错误。


管道和FIFO限制:

系统加于管道和FIFO的唯一限制为:

OPEN_MAX        一个进程在任意时刻打开的最大描述符数。(Posix要求至少为16)

PIPE_BUF          可原子地写往一个管道或FIFO的最大数据量。(Posix要求至少为512)

定义在头文件<limits.h>






























发布了98 篇原创文章 · 获赞 74 · 访问量 15万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章