Unix系统调用以升序然后降序打印数字

时间:2014-03-20 21:15:59

标签: c unix fork

我有一个小程序,需要按以下格式打印一些数字:

0 1 2 3 4
3
2
1
0

我尝试用这个C代码完成:

int main() {   
    int i;

    for (i = 0; i < 5 && !fork(); i++) {
        printf("%d ", i);
    }

    wait(NULL);

    return 0;
}

但这打印

0 1 2 3 4
0 1 2 3
0 1 2
0 1
0

我无法弄清楚如何省略额外的数字。任何人都可以看到什么是错的吗?

2 个答案:

答案 0 :(得分:1)

每次迭代fork都是一个新孩子。父对象退出循环和wait s,子进程打印迭代次数。但是,由于没有换行符,因此字符保持缓冲状态。但是,每个fork都会以当前状态复制缓冲区。因此,每个孩子都会继承其祖先的所有印刷值,并在退出前等待其孩子死亡。因此,就像最后一个子项退出一样,缓冲区看起来像这样:

parent:   ""
child-0 : "0 "
child-1 : "0 1 "
child-2 : "0 1 2 "
child-3 : "0 1 2 3 "
child-4 : "0 1 2 3 4 "

child-4退出(因为wait不会阻塞),导致其stdout缓冲区被刷新。这会导致child-3从wait返回并退出,导致其stdout缓冲区被刷新。这一直持续到父出口,所以你看到以下(所有在一行,因为在任何地方都没有新行):

0 1 2 3 4 0 1 2 3 0 1 2 0 1 0

要解决此问题,只需在打印前清空缓冲区即可。这会强制按顺序输出子缓冲区的子副本,然后当它们以相反的顺序退出时,子项的输出将出现:

int main() {   
    int i;

    for (i = 0; i < 5 && !fork(); i++) {
        fflush(stdout);
        printf("%d ", i);
    }

    wait(NULL);

    return 0;
}

给出:

0 1 2 3 4 3 2 1 0

答案 1 :(得分:0)

  1. 新线路在哪里?
  2. 操作系统可以自由选择一个进程而不是另一个进程。
  3. 需要考虑缓冲
  4. 你想做什么