【问题标题】:Child process read from pipe failed and seemed to be out of order从管道读取的子进程失败并且似乎出现故障
【发布时间】:2018-10-28 18:35:02
【问题描述】:

我有以下输出代码:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>

#define PIPE_STDIN  0
#define PIPE_STDOUT 1

#define msg "hello world"

int main()
{
   int fd_pipe[2];

   int ret = fork();
   if (ret < 0)
   {
       printf("Failed to fork\n");
       return -1;
   }
   else if (ret == 0)
   {
       printf("Parent with PID %d\n", getpid());    fflush(stdout);
       //sleep(3);
       ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg));   fflush(stdout);
       printf("Parent wrote string %d\n", ret);     fflush(stdout);
       wait( NULL );
       printf("Parent done wait\n");    fflush(stdout);
   }
   else
   {
       char buf[80];
       printf("Child with PID %d whose parent PID %d\n", getpid(), ret);    fflush(stdout);
       ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
       printf("Child read %s %d\n", buf, ret);  fflush(stdout);
   }
}

输出:

Child with PID 1130 whose parent PID 1131
Child read   -1
Parent with PID 1131
hello world Parent wrote string 12
Parent done wait

从输出中,为什么 child 无法从管道读取(返回 -1),然后打印了消息“hello world”?请解释给出上述日志的执行顺序。

【问题讨论】:

  • 你没有显示你在哪里调用pipe()——你使用的是随机文件描述符。
  • write() 调用之后的fflush(stdout) 基本上是空操作。
  • 常识规定fork()的结果是子进程的pid号,因为父进程pid总是可以通过getppid()系统调用得到,但是没有办法得到UNIX 中孩子的 pid,但直接从 fork() syscall 获取。
  • @JonathanLeffler, write()fflush() 实施之下。它对缓冲区一无所知(它不是stdio 的一部分),因此如果您执行write(2) 系统调用,缓冲区中可能会有数据。如果他改用fwrite(3),那就没什么好说的了。
  • @LuisColorado — 是的,但是write() 之前的电话也是fflush(stdout),所以正如我所说,之后的电话无关紧要。

标签: c linux process pipe fork


【解决方案1】:
  1. 你应该在fork之前调用pipe来初始化文件描述符。
  2. fork() == 0 表示子进程。

关注code 可以工作:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>

#define PIPE_STDIN  0
#define PIPE_STDOUT 1

#define msg "hello world"

int main()
{
   int fd_pipe[2];
   int ret;

   if (pipe(fd_pipe) == -1) {
       perror("pipe");
       return -1;
   }
   ret = fork();
   if (ret < 0)
   {
       printf("Failed to fork\n");
       return -1;
   }
   else if (ret != 0)
   {
       printf("Parent with PID %d\n", getpid());    fflush(stdout);
       //sleep(3);
       ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg));   fflush(stdout);
       printf("Parent wrote string %d\n", ret);     fflush(stdout);
       wait( NULL );
       printf("Parent done wait\n");    fflush(stdout);
   }
   else
   {
       char buf[80];
       printf("Child with PID %d whose parent PID %d\n", getpid(), getppid());    fflush(stdout);
       ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
       printf("Child read %s %d\n", buf, ret);  fflush(stdout);
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 2017-05-25
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 2018-12-11
    • 2014-02-25
    相关资源
    最近更新 更多