前面说到popen需要使用两个管道才能完成两个进程之间的双向通信,那么有没有直接支持双向通信的方法呢?有的,那就是无名管道。
无名管道有两个端口,一端点用于写,另一端用于读。这样一来两个进程都能通过无名管道完成读写,也就是双向通信。
对比项popenpipe数据类型仅字符型所有类型进程限制无父子关系通信方向单向双向 一、无名管道定义#include
int pipe(int file_descriptor[2]);
close(file_descriptor[0]);//关闭读端
close(file_descriptor[1]);//关闭写端
往编号为1的描述符写,从编号为0的描述符读回来,使用文件也能完成同样的功能,但是对于
输入参数
- int file_descriptor[2] 两个元素的整型数组
返回值
- int 正常返回
0
,异常返回-1
并设置errno
。
调用成功的结果 调用pipe
后将会填入文件描述符。
#include
#include
#include
#include
int main()
{
int pipes_fd[2];
const int damage=4396;
int buffer;
pid_t fork_result;
if(pipe(pipes_fd)==0)
{
fork_result=fork();
if(fork_result==-1)
{
fprintf(stderr,"Fork failure");
exit(EXIT_FAILURE);
}
if(fork_result==0)//son read father's story
{
read(pipes_fd[0],&buffer,sizeof(int));
printf("Son listening: %d",buffer);
}
else
{
write(pipes_fd[1],&damage,sizeof(damage));
printf("Father saying: %d",damage);
}
}
exit(EXIT_SUCCESS);
}
使用无名管道中存放的数据类型更加广泛。前面提到的popen
数据仅限于字符型数据。但是无名管道共享基础是,父子进程具有相同的文件描述符,如果没有亲缘关系的话,则不能使用无名管道了!
关于fork的返回值:
- 在父进程中,fork返回新创建子进程的进程ID;
- 在子进程中,fork返回0;
- 如果出现错误,fork返回一个负值;
前面都是读进程读到数据后直接退出并假设Linux帮助我们完成清理操作。事实上,大多数情况下我们并不知道有多少数据要读,所以常常使用循环read方式完成任务。整个过程如下:
Created with Raphaël 2.3.0
读数据
处理数据
仍有数据?
退出循环
yes
no
关于read的调用分为三种情况:
- 无数据,阻塞;
- 写端关闭,立即返回 0;
- 无效描述符,立即返回-1;
对于无名管道而言,只有当全部写端都关闭时,才会立刻返回0。
read是阻塞还是非阻塞读取取决于设备的设置,默认情况都是阻塞读取。
【1】《Linux程序设计(第五版)》