PIPE - Linux手册页

时间:2019-08-20 17:59:07  来源:igfitidea点击:

Linux程序员手册 第2部分
更新日期: 2020-06-09

名称

pipe, pipe2-创建管道

语法

#include <unistd.h>

/* On Alpha, IA-64, MIPS, SuperH, and SPARC/SPARC64; see NOTES */
struct fd_pair {
    long fd[2];
};
struct fd_pair pipe();

/* On all other architectures */
int pipe(int pipefd[2]);

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <fcntl.h>              /* Obtain O_* constant definitions */
#include <unistd.h>

int pipe2(int pipefd[2], int flags);

说明

pipe()创建一个管道,一个单向数据通道,可用于进程间通信。数组pipefd用于返回两个引用管道末端的文件描述符。 pipefd [0]是指管道的读取端。 pipefd [1]引用管道的写端。写入管道写入端的数据由内核缓冲,直到从管道读取端读取数据为止。有关更多详细信息,请参见pipe(7)。

如果标志为0,则pipe2()与pipe()相同。可以对标志中的以下值进行按位或运算以获得不同的行为:

O_CLOEXEC
在两个新的文件描述符上设置执行时关闭(FD_CLOEXEC)标志。有关为何可能有用的原因,请参见open(2)中相同标志的描述。
O_DIRECT(since Linux 3.4)

Create a pipe that performs I/O in "packet" mode.
Each
write(2)

to the pipe is dealt with as a separate packet, and
read(2)s

from the pipe will read one packet at a time.
Note the following points:

*
大于PIPE_BUF字节的写入(请参见pipe(7))将被拆分为多个数据包。常量PIPE_BUF在中定义。
*
如果read(2)指定的缓冲区大小小于下一个数据包,则将读取请求的字节数,并将丢弃该数据包中多余的字节。指定PIPE_BUF的缓冲区大小足以读取最大可能的数据包(请参阅上一点)。
*
不支持零长度数据包。 (将缓冲区大小指定为零的read(2)是无操作,并返回0。)
不支持此标志的较早内核将通过EINVAL错误指示这一点。
从Linux 4.5开始,可以使用fcntl(2)更改管道文件描述符的O_DIRECT设置。
O_NONBLOCK
在新文件描述符引用的打开文件描述上设置O_NONBLOCK文件状态标志。使用此标志可以节省对fcntl(2)的额外调用,以实现相同的结果。

返回值

成功时,返回零。如果出错,则返回-1,正确设置errno,并且pipefd保持不变。

在Linux(和其他系统)上,pipe()不会在失败时修改pipefd。在POSIX.1-2008 TC2中添加了标准化此行为的要求。特定于Linux的pipe2()系统调用同样不会在失败时修改pipefd。

错误说明

EFAULT
pipefd无效。
EINVAL
(pipe2())标志中的无效值。
EMFILE
已达到打开文件描述符数量的每个进程限制。
ENFILE
已达到系统范围内打开文件总数的限制。
ENFILE
已达到可以为管道分配的用户硬限制,并且调用者没有特权;参见pipe(7)。

版本

pipe2()已在2.6.27版中添加到Linux;从2.9版开始提供glibc支持。

遵循规范

pipe():POSIX.1-2001,POSIX.1-2008。

pipe2()是特定于Linux的。

备注

在某些体系结构上,System V ABI允许使用多个寄存器来返回多个值。若干体系结构(即Alpha,IA-64,MIPS,SuperH和SPARC / SPARC64)(ab)使用此功能,以便以功能方式实现pipe()系统调用:该调用不接受任何参数,并且返回一对文件描述符作为成功的返回值。 glibc pipe()包装函数透明地处理了这个问题。有关用于存储第二个文件描述符的寄存器的信息,请参见syscall(2)。

示例

下面的程序创建一个管道,然后fork(2)创建一个子进程。子级继承了引用同一管道的重复的文件描述符集。在fork(2)之后,每个进程都关闭不需要管道的文件描述符(请参阅pipe(7))。然后,父级将程序的命令行参数中包含的字符串写入管道,而子级一次从管道读取该字符串一个字节,并在标准输出中回显该字符串。

Program source

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int
main(int argc, char *argv[])
{
    int pipefd[2];
    pid_t cpid;
    char buf;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <string>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (cpid == 0) {    /* Child reads from pipe */
        close(pipefd[1]);          /* Close unused write end */

        while (read(pipefd[0], &buf, 1) > 0)
            write(STDOUT_FILENO, &buf, 1);

        write(STDOUT_FILENO, "\n", 1);
        close(pipefd[0]);
        _exit(EXIT_SUCCESS);

    } else {            /* Parent writes argv[1] to pipe */
        close(pipefd[0]);          /* Close unused read end */
        write(pipefd[1], argv[1], strlen(argv[1]));
        close(pipefd[1]);          /* Reader will see EOF */
        wait(NULL);                /* Wait for child */
        exit(EXIT_SUCCESS);
    }
}

另外参见

fork(2),read(2),socketpair(2),splice(2),tee(2),vmsplice(2),write(2),popen(3),pipe(7)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/