Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从管道读取的子进程失败,似乎出现了故障_C_Linux_Process_Pipe_Fork - Fatal编程技术网

C 从管道读取的子进程失败,似乎出现了故障

C 从管道读取的子进程失败,似乎出现了故障,c,linux,process,pipe,fork,C,Linux,Process,Pipe,Fork,我有以下带有输出的代码: #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]; in

我有以下带有输出的代码:

#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);
   }
}
从输出中,为什么孩子无法从管道中读取(返回-1),然后在稍后打印消息“hello world”?请解释给出上述日志的执行顺序

  • 您应该在
    fork
    之前调用
    pipe
    以初始化文件描述符
  • 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);
       }
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义管道标准0
    #定义管道标准件1
    #定义消息“hello world”
    int main()
    {
    int fd_管道[2];
    int ret;
    如果(管道(fd_管道)=-1){
    佩罗(“管道”);
    返回-1;
    }
    ret=fork();
    如果(ret<0)
    {
    printf(“未能分叉\n”);
    返回-1;
    }
    否则如果(ret!=0)
    {
    printf(“PID为%d的父项”,getpid());fflush(stdout);
    //睡眠(3);
    ret=写入(fd_管道[pipe_STDOUT],msg,sizeof(msg));fflush(STDOUT);
    printf(“父写入字符串%d\n”,ret);fflush(stdout);
    等待(空);
    printf(“父完成等待”);fflush(stdout);
    }
    其他的
    {
    char-buf[80];
    printf(“PID为%d且其父PID为%d的子项,\n”、getpid()、getppid());fflush(stdout);
    ret=读取(fd_管道[pipe_STDIN],buf,sizeof(msg));
    printf(“子读取%s%d\n”,buf,ret);fflush(stdout);
    }
    }
    
  • 您应该在
    fork
    之前调用
    pipe
    以初始化文件描述符
  • 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);
       }
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义管道标准0
    #定义管道标准件1
    #定义消息“hello world”
    int main()
    {
    int fd_管道[2];
    int ret;
    如果(管道(fd_管道)=-1){
    佩罗(“管道”);
    返回-1;
    }
    ret=fork();
    如果(ret<0)
    {
    printf(“未能分叉\n”);
    返回-1;
    }
    否则如果(ret!=0)
    {
    printf(“PID为%d的父项”,getpid());fflush(stdout);
    //睡眠(3);
    ret=写入(fd_管道[pipe_STDOUT],msg,sizeof(msg));fflush(STDOUT);
    printf(“父写入字符串%d\n”,ret);fflush(stdout);
    等待(空);
    printf(“父完成等待”);fflush(stdout);
    }
    其他的
    {
    char-buf[80];
    printf(“PID为%d且其父PID为%d的子项,\n”、getpid()、getppid());fflush(stdout);
    ret=读取(fd_管道[pipe_STDIN],buf,sizeof(msg));
    printf(“子读取%s%d\n”,buf,ret);fflush(stdout);
    }
    }
    
    您没有显示调用
    管道()
    -您使用的是随机文件描述符。调用
    write()
    之后的
    fflush(stdout)
    基本上是不可操作的。常识规定
    fork()
    的结果是子进程的pid号,因为父进程pid总是可以通过
    getppid()获得
    system调用,但在UNIX中无法获取子系统的pid,只能直接从
    fork()
    syscall获取。@JonathanLeffler,
    write()
    正在
    fflush()
    实现中。它对缓冲区一无所知(它不是
    stdio
    的一部分),因此如果只执行
    write(2)
    syscall,缓冲区中可能有数据。如果他使用了
    fwrite(3)
    ,则无需说明。@LuisColorado-是的,但是
    write()
    之前的调用也是
    fflush(stdout)
    ,因此后面的调用与我所说的无关。您没有显示调用
    pipe()
    -您使用的是随机文件描述符。
    fflush(stdout)
    write()
    调用之后,调用基本上是不可操作的。常识规定
    fork()
    的结果是子进程的pid号,因为父进程pid总是可以通过
    getppid()
    系统调用获得,但在UNIX中无法获得子进程的pid,只能直接从
    fork()获取
    syscall.@JonathanLeffler,
    write()
    正在
    fflush()
    实现中。它对缓冲区一无所知(它不是
    stdio
    的一部分),因此如果只执行
    write(2)
    syscall,缓冲区中可能有数据。如果他使用了
    fwrite(3)
    ,则无需说明。@LuisColorado-是的,但是
    write()
    之前的调用也是
    fflush(stdout)
    ,因此后面的调用与我所说的无关。