问题描述
我是编程过程的新手,我的基本程序实际上并没有达到我的预期。我正在Oracle VM的Ubuntu 18.04上运行此代码。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("--beginning of program\n");
int counter = 0;
pid_t pid = fork();
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i)
{
printf("child process: counter=%d\n",++counter);
}
}
else if (pid > 0)
{
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n",++counter);
}
}
else
{
// fork Failed
printf("fork() Failed!\n");
return 1;
}
printf("--end of program--\n");
return 0;
}
这是我总是得到的结果:
--beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
parent process: counter=4
parent process: counter=5
--end of program--
--beginning of program
child process: counter=1
child process: counter=2
child process: counter=3
child process: counter=4
child process: counter=5
--end of program--
这是我编译程序的命令:
gcc main.c -o main
谢谢!
解决方法
打印5个字符串的速度太快,父进程在子进程开始自己的循环之前就完成了它的循环。尝试更多循环,500个适用于我™。
请注意,父级和子级不共享内存。子级将继承counter = 0
,但不与其父级共享counter
。他们都将独立计数。协调流程需要更先进的技术。
其他问题。
您两次获得--end of program--
,因为子进程未退出。循环完成后,它将继续运行其余代码。向孩子添加exit(0)
。
如果您要在子进程完成后声明“结束”,请使用wait
等待子进程完成。
waitpid(pid,NULL,0);
printf("--end of program--\n");
如果输出是管道或文件(例如--beginning of program
或./program | cat
),则可以两次获得./program > output
。由于I / O缓冲。
写入磁盘速度很慢。它不是将所有内容在打印后立即写入,而是先写入内存,然后再写入磁盘。共有三种常见的缓冲类型:无缓冲,行缓冲和块缓冲。哪种缓冲取决于您要写入的内容。
无缓冲就是它所说的,您叫printf
并将其发送出去。 stderr
通常没有缓冲,因为重要的是要在发生错误时及时查看。
缓冲的行将输出存储在内存中,直到看到换行符,然后发送整行。发送它称为“刷新缓冲区”。 stdout
通常是行缓冲的。这是对终端在纸上实际打印一行的回溯。
这可能会导致奇怪的结果。
fprintf(stdout,"First");
fprintf(stderr,"Second");
fprintf(stdout,"Third\n");
由于stdout
是行缓冲区,结果将是SecondFirstThird
。
除非 stdout
或stderr
不会进入终端。如果要转到管道或文件,则可能是块缓冲。这意味着输出将被缓冲,直到看到一定数量的数据为止,然后将其刷新。
在您的代码中,如果stdout
被行缓冲printf("--beginning of program\n");
被立即刷新。但是,如果stdout
重定向到文件,则会对其进行块缓冲并且不会立即写入。 "--beginning of program\n"
仍在stdout
的缓冲区中。当您分叉时,子级将获得该缓冲区的副本并添加到该缓冲区中。因此,孩子和父母都打印"--beginning of program\n"
。
您可以通过在使用fflush
进行分叉之前显式刷新stdout缓冲区来解决此问题。
printf("--beginning of program\n");
fflush(stdout);
,
您所获得的输出将根据您拥有的当前代码而有所不同。例如,当我运行代码时,流程调度程序决定先运行父流程,然后运行子流程,然后再运行到父流程,直到它们都完成。
查看所附图片。
但是,在您的情况下,流程调度程序先运行父级并完成,然后运行子级并完成。
如果您希望孩子先运行,那么父母可以在父母中使用wait(&status)来确保孩子先运行。参见下面的代码。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
printf("--beginning of program\n");
int counter = 0;
int wait3,status;
pid_t pid = fork();
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i)
{
printf("child process: counter=%d\n",++counter);
}
}
else if (pid > 0)
{
wait3 = wait(&status);
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n",++counter);
}
}
else
{
// fork failed
printf("fork() failed!\n");
return 1;
}
printf("--end of program--\n");
return 0;
}