a941042997 2018-10-20 04:14 采纳率: 0%
浏览 990

请教,fork(),pipe()和execlp()组合使用,pipe()不能实时获取数据的原因。

很简单的两个小程序。第一个程序是子进程调用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);
    }
}

运行结果

  • 写回答

1条回答 默认 最新

  • 流星杀手剑 2018-10-23 09:58
    关注

    将最后一个 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去掉。

    评论

报告相同问题?

悬赏问题

  • ¥15 slam rangenet++配置
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊