【问题标题】:Issue with fork and wait system call分叉和等待系统调用的问题
【发布时间】:2013-06-30 14:23:13
【问题描述】:

我用 fork() 和 wait() 系统调用在 unix 中编写了一个基本的 c++ 程序。我只创造一个孩子。我用过两根管子。因此,在使用第一个管道进行分叉操作后,我正在从子级向父级写入,并且在父级接收到数据后,父级在第二个管道中回写给子级。之后在父方我使用 wait(0) 系统调用。但我的父进程仍然在子进程之前死亡?

结构是这样的:

 main()
 char buff[] = "Parent process kills";
 char cuff[] = "before Child process";
 int fd1[2];
 int fd2[2];
 pipe(fd1);
 pipe(fd2);
 if((pid = fork()) == 0)
 {
   close(fd1[0]);
   close(fd2[1]);
   write(fd1[1],buff,strlen(buff)+1);
   read(fd2[0],cuff,sizeof(cuff));

 }
 else
 {
    close(fd1[1]);
    close(fd2[0]);

    read(fd1[0],buff,sizeof(buff));
    write(fd2[1],cuff,strlen(cuff)+1);
    wait((int *) 0);
  }

  close(fd1);
  close(fd2);

  }'

即使使用了 wait(),但父进程仍然在子进程之前死亡。 提前致谢。

【问题讨论】:

  • 请记住fork 可能会失败,在这种情况下会返回-1。因此,您的 if 语句在这种情况下将不起作用。您应该始终检查失败的返回值。

标签: c++ fork pipe wait


【解决方案1】:

您对read 的调用会导致未定义的行为。您尝试读入字符串文字,而不是您拥有的缓冲区。在这种情况下,它可能会导致崩溃。

您的 write 调用还会写入字符串文字,而不是您拥有的缓冲区。

此外,由于您将字符数组初始化为字符串,sizeo(buff)strlen(buff) + 1 是相等的。

【讨论】:

    【解决方案2】:

    你确定你不会因为段错误而死吗?这些命令中的每一个都试图发送超出您预期的内容:

    write(fd1[1],"buff",strlen(buff)+1);
    

    write(fd2[1],"cuff",strlen(cuff)+1);
    

    其中每一个都试图接收到只读内存:

    read(fd2[0],"cuff",sizeof(cuff));
    

    read(fd1[0],"buff",sizeof(buff));
    

    【讨论】:

    • 在accutal code is 这是accutal code。请查看此代码解释为什么父进程在子进程之前退出。 main() pid_t pid; char buff[] = "父进程杀死"; char cuff[] = "在子进程之前";诠释 fd1[2];诠释 fd2[2];管道(fd1);管道(fd2); if((pid = fork()) = 0) { 关闭(fd1[0]);关闭(fd2[1]);写(fd1 [1],buff,strlen(buff)+1);读取(fd2 [0],袖口,sizeof(袖口)); } 否则 { 关闭(fd1[1]);关闭(fd2[0]);读取(fd1 [0],buff,sizeof(buff));写(fd2[1],袖口,strlen(袖口)+1);等待((int *) 0); } 关闭(fd1);关闭(fd2); }
    【解决方案3】:

    行中有一个细微的错误

    if(pid == fork())
    

    您将 fork() 的结果与 pid 进行比较,而不是分配给它并将其与零进行比较。你想写的是这样的:

    if((pid = fork()))
    

    注意额外的括号集,告诉编译器您确实想要执行分配,并且您不希望收到警告。

    如果更正后,您让父级执行第一种情况,而不是第二种情况,所以正确的代码是:

    if(pid == fork()) {
      close(fd1[1]);
      close(fd2[0]);
    
      read(fd1[0],"buff",sizeof(buff));
      write(fd2[1],"cuff",strlen(cuff)+1);
      wait((int *) 0);
    } else {
      close(fd1[0]);
      close(fd2[1]);
      write(fd1[1],"buff",strlen(buff)+1);
      read(fd2[0],"cuff",sizeof(cuff));
    }
    

    【讨论】:

    • 这是准确的代码。请查看此代码解释为什么父进程在子进程之前退出。 main() pid_t pid; char buff[] = "父进程杀死"; char cuff[] = "在子进程之前";诠释 fd1[2];诠释 fd2[2];管道(fd1);管道(fd2); if((pid = fork()) = 0) { 关闭(fd1[0]);关闭(fd2[1]);写(fd1 [1],buff,strlen(buff)+1);读取(fd2 [0],袖口,sizeof(袖口)); } 否则 { 关闭(fd1[1]);关闭(fd2[0]);读取(fd1 [0],buff,sizeof(buff));写(fd2[1],袖口,strlen(袖口)+1);等待((int *) 0); } 关闭(fd1);关闭(fd2); }
    • 请记住,单个等号始终是一个赋值。所以if((pid = fork()) = 0)首先把返回值赋给pid,然后给它赋零,这也是整个表达式的值。零是假的。因此,子进程和父进程都执行else 子句。因此,两个进程在读取管道时都关闭了管道的同一端=>,不再有写端打开。请查看 pipe 的手册页,您会找到一个完整的工作示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多