分叉时的 Printf 行为

Printf behaviour when forking

我正在尝试构建一个 C 程序,其中 parent 创建一个可用源数组,然后 fork 一些孩子以做某事。在此阶段,孩子们使用 parent 的 "available" 数组创建一个数组,并使用他们刚刚创建的数组创建另一个数组。

这是我的代码:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
    pid_t wpid;

    int i = 0;
    int j = 0;
    int status = 0;
    int sources = 3;
    int children = 3;


    int *available = malloc(sources * sizeof(int));

    for (i = 0; i < sources; i++)
        available[i] = 20;

    for (i = 0; i < children; i++)
    {
        pid_t pid = fork();

        if (pid == 0)
        {
            // kid gets here
            srand(getpid());

            printf("Kid %d created!\n", getpid());

            int *total = malloc(sources * sizeof(int));
            int *request = malloc(sources * sizeof(int));

            for (j = 0; j < sources; j++){
                total[j] = rand() % (available[j] / 2);
                printf("Kid(%d): Source(%d) = %d\n", getpid(), j, total[j]);
            }


            for (j = 0; j < sources; j++){
                request[j] = rand() % total[j];
                printf("REQUEST: Kid(%d): Source(%d) = %d\n", getpid(), j, request[j]);
            }

            printf( "==============================================================\n");


            free(total);
            free(request);

            exit(0);
        }
        // parent gets here

        sleep(1);   // readable reasons
    }

    while ((wpid = wait(&status)) > 0);

    free(available);

    return 0;
}

问题

问题是有时当我 运行 这个程序时,我没有在我的终端中得到所有的打印件。例如,第二个循环应该正好打印 3 次 REQUEST: blabla 但有时只打印两次或根本不打印。

我试过的

1) 据此post printf anomaly after "fork()", "when the output of your program is going to a terminal (screen), it is line buffered"。但是我所有的打印件最后都有一个 '\n' 所以我不应该对 printf 的缓冲有问题。

2) 每次打印后都尝试 'fflush(stdout)'。

3) 尝试使用 fprintf 打印到 stderr。

那么为什么有些打印没有出现呢?

子进程在 total[j]0 时退出,因为 rand() % total[j] 出现被零除错误。

改变

request[j] = rand() % total[j];

request[j] = total[j] ? rand() % total[j] : -1;

这将跳过这种情况下的除法,并将 -1 放入 request 以指示错误的情况。

这实际上与分叉没有任何关系,除非您在父进程中有循环 shell 会告诉您进程正在崩溃。您的父进程没有报告 wait() returns 的退出状态,所以您看不到这个。