fork 系统调用
Description
- fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process
代码例子
/*************************************************************************
> File Name: fork0.c
> Author:perrynzhou
> Mail:perrynzhou@gmail.com
> Created Time: Tue 11 Jun 2019 10:27:20 AM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
void usage(char *s)
{
printf("%s -f {0 | 1}\n", s);
printf(" 1 -- force flush all opened stream before fork\n");
printf(" 0 -- not flush all opened stream before fork\n");
}
bool is_number(const char *s)
{
if (s == NULL)
{
return false;
}
while (*s != '\0')
{
if (isdigit(*s++) == 0)
{
return false;
}
}
return true;
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
usage(argv[0]);
exit(0);
}
const char *cmd_parse_fmt = "f:";
char ch;
int force_flush_flag = 0;
while ((ch = getopt(argc, argv, cmd_parse_fmt)) != -1)
{
switch (ch)
{
case 'f':
if (!is_number(optarg))
{
force_flush_flag = -1;
}
else
{
force_flush_flag = atoi(optarg);
}
break;
default:
break;
}
}
if (force_flush_flag > 1 || force_flush_flag < 0)
{
usage(argv[0]);
exit(0);
}
printf("flush opened stream :%d\n", force_flush_flag);
printf("[%ld]begin\n", getpid());
pid_t pid;
if (force_flush_flag == 1)
{
fflush(NULL);
}
if ((pid = fork()) < 0)
{
perror("fork");
exit(0);
}
else if (pid == 0)
{
printf("[%ld] child process working\n", getpid());
exit(0);
}
else
{
printf("[%ld] parent process working\n", getpid());
}
return 0;
}
标准输出

image.png
文件输出

image.png
- 文件输出 f=1和f=0 结果完全不同,这是为什么?
标准输出和文件输出
- 标准输入输出是行缓冲模式(\n,强制输出),在终端执行fork之前的printf,都是执行一次。
- 文件输入输出是全缓冲模式(buffer到了指定的size,才会输出)
- 当执行 test_fork -f 0重定向文件 时候,父进程执行fork之后,父子进程的地址空间是cow,没有任何改动的前提下,都是执行同一个地址空间。此时,父子进程执行的缓冲区都是一模一样,所以可以看到父子进程都会执行fork之前的printf.所以文件看到的是2个"flush opened stream :0"和"[92741]begin".
- 当f=1,重定向文件时候可以看到,父子进程仅仅执行一次 "flush opened stream :1"和"[92741]begin".原因在于f=1的时候会在父进程fork之前执行fflush(NULL),此时执行这个函数目的在于强制flush所有的已经打开的stream.
网友评论