【问题标题】:Forking WITHOUT waiting分叉无需等待
【发布时间】:2014-04-06 02:49:38
【问题描述】:

我不确定我是否正确执行此操作,我正在尝试通过...创建总共 7 个进程...

void err_sys(const char* x)
{
   perror(x);
   exit(1);
}


for(i = 1; i < 7; i++){
  switch(parent = fork()){
      case -1:
         err_sys("fork error");
      case 0:       //child
         printf("I'm the child, number %d(%d)\n", i, getpid());
         break;
      default:      //parent
         printf("I'm the parent(%d)\n", getpid());
         break;
  }
    if(parent)
       break;        //loop break
}

当我用 prog | 运行它时cat > file 我得到 6 个“我是父母”的输出,每个输出都有不同数量的孩子。但是,有 6 个孩子是用独特的 pid 制作的。其他父 pid,除了第一个匹配子 pid。这只是由于分叉而导致输出的一些问题吗?

【问题讨论】:

    标签: c switch-statement fork wait


    【解决方案1】:

    您的代码不正确先验;它做它做的事。问题是“它是否按照您的意愿去做”,这并不清楚,因为您没有明确说明您要做什么。

    你得到 6 个进程的一个原因是你有一个循环:

    for (i = 1; i < 7; i++)
    

    这计数 1、2、3、4、5、6 并停止。您需要使用以下两个成语之一:

    for (i = 0; i < 7; i++)      // Idiomatic C
    for (i = 1; i <= 7; i++)     // Less idiomatic C
    

    假设err_sys() 在被调用时没有返回(如果返回,你需要在它后面加上break;),那么:

    1. 进程分叉。如果分叉失败,进程通过err_sys()退出。
    2. 如果进程是子进程(因此将错误命名的变量 parent 设置为 0),则代码会打印“我是子进程”,然后离开开关,再次围绕循环进行迭代。
    3. 如果进程是父进程(因此错误命名的变量 parent 设置为非零值),它会打印“我是父进程”,然后离开开关和循环。

    只有第一个 fork 的子节点才能重新执行循环。但是,除了最后一个子元素之外,每个子元素都会在循环的下一次迭代中将自己标识为父元素。

    缓冲 I/O

    请注意,缓冲 I/O 会使事情复杂化。如果将程序的输出写入终端,默认情况下会得到行缓冲输出。每个换行符都会将数据写入终端。但是,当输出进入管道时,它是完全缓冲的;数据仅在缓冲区已满或进程退出(或因其他原因关闭标准输出)时才写入终端。因此,当输出进入管道时,第一个子节点仅具有其操作的输出,但第二个子节点在其缓冲区中的第一个子节点及其写入的内容中打印但未刷新的数据。第三个孩子有 3 个进程的输出,以此类推。

    您可以在打印语句之后添加fflush(0)fflush(stdout)(或在switch 结束之后,在if 之前),看看它有什么不同。您还可以在不重定向到管道的情况下运行代码,看看有什么不同。

    【讨论】:

    • 你怎么不赞成这样的问题?它看起来足够清晰和完整。
    • @wallyk:通常,我不会对一个问题投赞成票,因为我已经足够频繁地(并且最近)回答了足够相似的问题,以至于它不符合我的“新奇”标准,甚至虽然我不一定会费心去追赶重复的东西。例如,Using fork() in an if statement — managing processes 基本上是关于相同的问题。没错,这使用了switch 而不是if,但这是偶然的。然后是fork() function process graph,还有……
    • 哦,我不知道问题的独特性或新颖性是标准的一部分。 upvote 悬停文本是 This question 显示研究工作;它有用且清晰(再次单击可撤消).
    • @JonathanLeffler:通过迭代获得 6 个孩子,我的父进程不计入第 7 个进程吗?还添加了 err_sys 以显示功能。
    • @DanielAnthony:这取决于您要如何计算。有6个子进程;有6个父进程;使用了 7 个单独的进程 ID。 (有一个父进程从不认为自己是子进程;有一个子进程从不认为自己是父进程;另外 5 个将自己视为子进程和父进程。)您的代码创建了 6 个进程;第七个是由外壳先验地创建的。我认为不值得大惊小怪。 5、6、7、8 几乎都是一样的——确实,有趣的数字是零、一、多。
    猜你喜欢
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多