Raj*_*Rao 3 c buffer operating-system fork system-calls
我正在尝试学习 UNIX 编程,并遇到了一个问题fork()
,我无法解释下面 2 个程序的输出。
我知道这fork()
会创建与当前正在运行的进程相同的进程,但它从哪里开始呢?例如,如果我有下面这两个程序,输出是什么以及它是如何工作的?
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main (int argc, char **argv)
{
int retval;
printf ("This is most definitely the parent process\n");
// now here fork will create a child process
// i need to know from which line child process starts execution
retval = fork ();
printf ("Which process printed this?\n");
return (0);
}
Run Code Online (Sandbox Code Playgroud)
在子进程执行方面,上面的程序和下面的程序有什么区别:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main (int argc, char **argv)
{
int retval;
printf ("This is most definitely the parent process\n");
fflush (stdout);
// how does fflush change the output of above program and why ?
// even though no string operations are being used
retval = fork ();
printf ("Which process printed this?\n");
return (0);
}
Run Code Online (Sandbox Code Playgroud)
我认为他们都应该打印:
This is most definitely the parent process
Which process printed this?
Which process printed this?
Run Code Online (Sandbox Code Playgroud)
但第一个是打印:
This is most definitely the parent process
Which process printed this?
This is most definitely the parent process
Which process printed this?
Run Code Online (Sandbox Code Playgroud)
我知道 fork() 创建与当前正在运行的进程相同的进程,但它从哪里开始呢?
如果fork(2)
成功(即不返回-1
),则从调用 的行开始fork(2)
。fork(2)
返回两次:在子进程中返回 0,C
在父进程中返回正数,其中C
是新生子进程的进程 ID。
您看到This ismostly theparentprocesstwice的原因与 stdio 的缓冲有关。Stdio 缓冲用户空间缓冲区中的输出,仅当发生某些情况(例如缓冲区已满)时才会刷新这些缓冲区。缓冲模式决定了何时以及如何刷新缓冲区。
通常,如果将输出写入交互式设备(例如终端(或伪终端)),则 stdio 是行缓冲的fflush(3)
,这意味着在找到或调用换行符时刷新缓冲区。
OTOH,如果输出重定向到文件或其他非交互式设备(例如,输出重定向到管道),则 stdio 是完全缓冲的,这意味着缓冲区仅在缓冲区已满或被fflush(3)
调用时才会刷新。
因此,如果没有fflush(3)
,在终端设备中执行代码将打印以下内容:
This is most definitely the parent process
Which process printed this?
Which process printed this?
Run Code Online (Sandbox Code Playgroud)
这是预料之中的。但是,如果您通过管道它cat(1)
,您将看到这个(或其他一些变体,取决于执行顺序):
This is most definitely the parent process
Which process printed this?
This is most definitely the parent process
Which process printed this?
Run Code Online (Sandbox Code Playgroud)
这是因为输出在重定向到管道时被完全缓冲。该字符串This is most definitely the parent process
不足以填充和刷新缓冲区,因此当父进程分叉时,子进程(获取父进程内存空间的副本)将获取输出缓冲区的副本,其中已包含 string This is most definitely the parent process
。所以两个进程最终都会打印该字符串。
如果您总是fflush(3)
在分叉之前调用,则不会发生这种情况,因为当将父级的内存空间复制到子级时,缓冲区为空。