管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。管道的这一特点决定了器使用的局限性。管道是Linux支持的最初Unix IPC形式之一,具有以下特点:
数据只能由一个进程流向另一个进程(其中一个读管道,一个写管道);如果要进行双工通信,需要建 立两个管道。
管道只能用于父子进程或者兄弟进程间通信。,也就是说管道只能用于具有亲缘关系的进程间通信。
除了以上局限性,管道还有其他一些不足,如管道没有名字(匿名管道),管道的缓冲区大小是受限制的。管道所传输的是无格式的字节流。这就需要管道输入方和输出方事先约定好数据格式。虽然有那么多不足,但对于一些简单的进程间通信,管道还是完全可以胜任的。
使用管道进行通信时,两端的进程向管道读写数据是通过创建管道时,系统设置的文件描述符进行的。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,可以克服使用文件进行通信的两个问题,这个文件只存在内存中。
通过管道通信的两个进程,一个进程向管道写数据,另外一个从中读数据。写入的数据每次都添加到管道缓冲区的末尾,读数据的时候都是从缓冲区的头部读出数据的。
#include
int pipe(int pipefd[2]);
(匿名)管道两端分别用描述符pipefd[0]及pipefd[1]来描述。需要注意的是,管道两端的任务是固定的,一端只能用于读,有描述符pipefd[0]表示,称其为管道读端;另一端只能用于写,由描述符pipe[1]来表示,称其为管道写端。该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信。
1. 函数说明
pipe(建立管道):
1) 头文件 #include
2) 定义函数: int pipe(int filedes[2]);
3) 函数说明: pipe()会建立管道,并将文件描述词由参数filedes数组返回。
filedes[0]为管道里的读取端
filedes[1]则为管道的写入端。
4) 返回值: 若成功则返回零,否则返回-1,错误原因存于errno中。
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int filedes[2];
charbuf[80];
pid_t pid;
pipe( filedes );
pid=fork();
if(pid > 0)
{
printf("This is in the father process,here write a string to the pipe.\n");
chars[] ="Hello world , this is write by pipe.\n";
write( filedes[1], s,sizeof(s) );
close( filedes[0] );
close( filedes[1] );
}
elseif(pid == 0)
{
printf("This is in the child process,here read a string from the pipe.\n");
read( filedes[0], buf,sizeof(buf) );
printf("%s\n", buf );
close( filedes[0] );
close( filedes[1] );
}
waitpid( pid, NULL, 0 );
return0;
}
运行结果:
[root@localhost src]# gcc pipe.c
[root@localhost src]# ./a.out
This is in the child process,here read a string from the pipe.
This is in the father process,here write a string to the pipe.
Hello world , this is write by pipe.
当管道中的数据被读取后,管道为空。一个随后的read()调用将默认的被阻塞,等待某些数据写入。