很简单的两个小程序。第一个程序是子进程调用execlp()打开第二个程序。父进程经过pipe()获取子进程的输出数据。
第二个程序是每秒printf()一句话。
需求是程序2每printf()一次,父进程就实时打印一句。
但现在结果是,父进程只能等程序2运行结束才能获取到管道的数据。
int main()
{
char buffer[1024]={0};
int len;
int pfd[2];
pid_t pid;
if(pipe(pfd)<0)
return -1;
fcntl(pfd[0], F_SETFL, O_NONBLOCK );
fcntl(pfd[1], F_SETFL, O_NONBLOCK );
pid =fork();
if(pid <0)
{
return -1;
}
else if(pid== 0)
{
dup2(pfd[1],STDOUT_FILENO);
close(pfd[0]);
close(pfd[1]);
execlp("./test4.out" ,"",NULL);
exit(0);
}
close(pfd[1]);
while(1)
{
len=read(pfd[0],buffer,1023);
buffer[len]=0;
printf("len=%d\n %s\n",len,buffer);
sleep(1);
}
return 0;
}
int main(int argc,char **argv)
{
int i=0;
while(i<10)
{
printf("i=%d\n",i++);
sleep(1);
}
}
将最后一个 1023 改成 6。
但这样问题还没解决,你需要理解非阻塞IO才能明白问题所在。
你将管道读端和写端都设置为非阻塞,那么文件是怎样执行的呢?
非阻塞读中:
父进程会不断地读pfd[0],直到字符数达到1023个,才会返回:
若没有读取到数据,则不会像阻塞读一样等待,而是直接返回。//此时 len = 0
while(1)
{
len=read(pfd[0],buffer,1023); //直到1023个字符才会执行下一句
buffer[len]=0; //若执行到此,len一定为1023
printf("len=%d\n %s\n",len,buffer);//由于read最多只能读到40,所以永远不可能执行这句话
sleep(1);
}
若为阻塞读:
只要有数据读取到,就会返回。
若没有读到数据,就会等待,直到读到数据。
非阻塞写中:
在全部写完后,非阻塞读才会开始读,所以前面才会有那么多len = -1,因为还没开始读。不信你把第二个文件中的sleep去掉。