分叉时的 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 的退出状态,所以您看不到这个。
我正在尝试构建一个 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 的退出状态,所以您看不到这个。