[英]fork() and wait() calls
我对以下代码有疑问。 这是在此页面上找到的示例,而不是我的代码。
父进程分叉2个子进程,每个进程计数到200,然后退出。 我不明白的是,为什么孩子们在分叉后立即打印他们的信息并允许他们的父亲进入等待状态? 另外,等待系统调用如何返回首先完成的子进程的pid?
pid =等待(和状态);
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#define MAX_COUNT 200
#define BUF_SIZE 100
void ChildProcess(char [], char []); /* child process prototype */
void main(void)
{
pid_t pid1, pid2, pid;
int status;
int i;
char buf[BUF_SIZE];
printf("*** Parent is about to fork process 1 ***\n");
if ((pid1 = fork()) < 0) {
printf("Failed to fork process 1\n");
exit(1);
}
else if (pid1 == 0)
ChildProcess("First", " ");
printf("*** Parent is about to fork process 2 ***\n");
if ((pid2 = fork()) < 0) {
printf("Failed to fork process 2\n");
exit(1);
}
else if (pid2 == 0)
ChildProcess("Second", " ");
sprintf(buf, "*** Parent enters waiting status .....\n");
write(1, buf, strlen(buf));
pid = wait(&status);
sprintf(buf, "*** Parent detects process %d was done ***\n", pid);
write(1, buf, strlen(buf));
pid = wait(&status);
printf("*** Parent detects process %d is done ***\n", pid);
printf("*** Parent exits ***\n");
exit(0);
}
void ChildProcess(char *number, char *space)
{
pid_t pid;
int i;
char buf[BUF_SIZE];
pid = getpid();
sprintf(buf, "%s%s child process starts (pid = %d)\n",
space, number, pid);
write(1, buf, strlen(buf));
for (i = 1; i <= MAX_COUNT; i++) {
sprintf(buf, "%s%s child's output, value = %d\n", space, number, i);
write(1, buf, strlen(buf));
}
sprintf(buf, "%s%s child (pid = %d) is about to exit\n",
space, number, pid);
write(1, buf, strlen(buf));
exit(0);
}
输出MAX_COUNT 40。
*** Parent is about to fork process 1 ***
*** Parent is about to fork process 2 ***
*** Parent enters waiting status .....
First child process starts (pid = 3300)
First child's output, value = 1
Second child process starts (pid = 3301)
Second child's output, value = 1
First child's output, value = 2
Second child's output, value = 2
Second child's output, value = 3
First child's output, value = 3
Second child's output, value = 4
First child's output, value = 4
Second child's output, value = 5
First child's output, value = 5
Second child's output, value = 6
First child's output, value = 6
Second child's output, value = 7
First child's output, value = 7
Second child's output, value = 8
First child's output, value = 8
Second child's output, value = 9
First child's output, value = 9
Second child's output, value = 10
First child's output, value = 10
Second child's output, value = 11
First child's output, value = 11
Second child's output, value = 12
First child's output, value = 12
Second child's output, value = 13
First child's output, value = 13
Second child's output, value = 14
First child's output, value = 14
Second child's output, value = 15
First child's output, value = 15
Second child's output, value = 16
First child's output, value = 16
Second child's output, value = 17
First child's output, value = 17
Second child's output, value = 18
First child's output, value = 18
Second child's output, value = 19
First child's output, value = 19
Second child's output, value = 20
First child's output, value = 20
Second child's output, value = 21
First child's output, value = 21
Second child's output, value = 22
First child's output, value = 22
Second child's output, value = 23
First child's output, value = 23
Second child's output, value = 24
First child's output, value = 24
Second child's output, value = 25
First child's output, value = 25
Second child's output, value = 26
First child's output, value = 26
Second child's output, value = 27
First child's output, value = 27
Second child's output, value = 28
First child's output, value = 28
Second child's output, value = 29
First child's output, value = 29
Second child's output, value = 30
First child's output, value = 30
Second child's output, value = 31
First child's output, value = 31
Second child's output, value = 32
First child's output, value = 32
Second child's output, value = 33
First child's output, value = 33
Second child's output, value = 34
First child's output, value = 34
Second child's output, value = 35
First child's output, value = 35
Second child's output, value = 36
First child's output, value = 36
Second child's output, value = 37
First child's output, value = 37
Second child's output, value = 38
First child's output, value = 38
Second child's output, value = 39
First child's output, value = 39
Second child's output, value = 40
First child's output, value = 40
Second child (pid = 3301) is about to exit
First child (pid = 3300) is about to exit
*** Parent detects process 3300 was done ***
*** Parent detects process 3301 is done ***
*** Parent exits ***
为什么*** Parent enters waiting status .....
行开头显示,而不是孩子开始打印后的某个地方?
Fork创建一个新进程,可以与父进程同时(或交错)执行。 它不会使父进程停止。 在fork
调用之后,两个进程都是“可运行的”,并且它们很可能都在运行。 如果父进程是幸运的,那么它将是第一个能够输出的进程。 一般来说,这是不可预测的。
该代码中存在许多错误,因此我不会将其视为学习如何使用fork()
的良好来源。
例如,父进程使用printf
来编写消息:
*** Parent is about to fork process 1 ***
*** Parent is about to fork process 2 ***
但是, stdout
很可能不是行缓冲的(例如,它可能被重定向。)在这种情况下,输出只会被复制到内存中的输出缓冲区,并且当缓冲区将被打印到stdout
填充或关闭stdout
文件描述符。 但是,子*** Parent is about to fork process 1 ***
将分配相同的内存输出缓冲区,因此父*** Parent is about to fork process 1 ***
和子*** Parent is about to fork process 1 ***
将输出*** Parent is about to fork process 1 ***
进程将*** Parent is about to fork process 1 ***
消息,所有三个进程将输出*** Parent is about to fork process 2 ***
消息。
此外,如果将stdout
重定向到未在追加模式下打开的可搜索流,则每个进程的文件描述符1将具有相关的文件位置,每个位置将独立操作。 这可能导致两个子进程覆盖彼此的输出。 (在我的系统上,覆盖发生在大约80%的时间。)
在非繁忙的多核或多处理器系统中,孩子很可能几乎立即开始执行。 在Unix和Linux上,分叉是一种快速简便的操作:复制一些内存描述符,复制一些资源,修复一些信号逻辑并使两个进程都可以运行。 调度程序是不可预测的(在此级别的观察中):它旨在公平公正。
此外,孩子们做的更多是计算重量级的格式化文本,在CRTL中缓冲它,可能将其转移到i / o系统 - 而不是父语件:fork(),比较数字,wait()。
所以父母很快就会进入wait()就不足为奇了,因为它不再竞争CPU时间。
使用fflush(stdout)
在每个printf()
之后可能(或可能不)通过从混合中移除两级i / o缓冲来提高一致性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.