进程间通信--pipe
管道的两种局限性:
- 历史上,他们是半双工的(即数据只能够在一个方向上流动). 现在某些系统也提供全双工管道,但是为了最佳的移植性,我们决不应该预先假定系统使用此特性
- 他们只能够在具有公共祖先的进程间使用. 通常一个管道由一个进程创建, 然后该进程通过调用fork, 此后父,子进程之间就可以使用该管道
尽管有这两种局限, 但半双工管道仍然是最常用的 IPC 形式.
管道由调用pipe函数创建:
#include<unistd.h>
int pipe(int filedes[2]);
返回值: 0: 成功, -1: 失败
经由参数filedes返回的两个文件描述符:
filedes[0]: 读
filedes[1]: 写
filedes[1]的输出既是filedes[0]的输入
由此, 调用fork之后做什么取决于我们想要有的数据流动方向. 对于从父进程到子进程的管道, 父进程关闭管道的读端filedes[0], 子进程则关闭写端filedes[1]. 如代码所示:
/*******************************************************************************
* 版权所有:
* 模 块 名:
* 文 件 名:pipe.c
* 实现功能:
* 作 者:XYZ
* 版 本:V1.0
* 日 期:2013.08.19
* 其他说明:创建一个从父进程到子进程的管道,并且父进程经改管道向子进程传递数据
********************************************************************************/
// pipe.c
#include<stdio.h>
#include"apue.h"
int main()
{
int n;
int fd[2];
pid_t pid;
char line[MAXLINE];
if (pipe(fd) < 0)
{
perror("pipe error");
}
if ((pid = fork()) < 0)
{
perror("fork error");
}
else if (pid > 0)
{
// parent
close(fd[0]); // close the read pipe
write(fd[1], "hello world\n", 12);
}
else
{
// chlid
close(fd[1]); // close the write pipe
n = read(fd[0], line, MAXLINE);
write(STDOUT_FILENO, line, n);
}
exit(0);
}
相反, 为了构造从子进程到父进程的管道, 则父进程关闭了写端fd[1], 子进程需关闭读端fd[0].
当管道的一端被关闭后, 有以下两条规则起作用:
- 当读一个写端已被关闭的管道时,在所有数据都被读取后,read返回0, 以指示达到了文件的结束处.(从技术方面考虑,管道的写端还有进程时,就不会产生文件的结束.可以复制一个管道的描述符,使得有多个进程对他具有写打开文件描述符. 但是 ,通常一个管道只有一个读进程,一个写进程)
- 如果写一个读端已被关闭的管道, 则产生信号SIGPIPE.如果忽略该信号或者捉该信号并从其处理程序返回,则write返回-1, error设置为EPIPE.
在写管道FIFO时,常量PIPE_BUF规定了内核中管道缓冲区的大小.如果对管道调用write,而且要求写的字节数小于等于PIPE_BUF,则此操作不会与其他进程对同一个管道的write操作穿插进行. 但是, 要是有多个进程同时写一个管道,而且有进程要求写的字节数超过PIPE_BUF字节时, 则写操作的数据可能会相互穿插. 用pathconf或者fpathconf函数可以确定PIPE_BUF的值.
浙公网安备 33010602011771号