代码改变世界

Linux -- 进程管理之 fork() 函数

2019-11-25 17:12  陈心朔  阅读(379)  评论(0编辑  收藏  举报

一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

Test1

for(int i = 0; i<2; i++)
{
    if(fork() == 0)
        printf("A\n");
    else
        printf("B\n");
}

上述代码中,fork() 执行后会出现两个进程,子进程中的 fork() 返回值为 0,父进程中 fork() 返回值则是子进程的 pid
执行结果如下图

Test2

将上述代码稍微修改一下

for(int i = 0; i<2; i++)
{
    if(fork() == 0)
        printf("A");
    else
        printf("B");
}

该循环中打印没有字符 "\n",无法刷新缓冲区
每一次 fork() 会复制之前进程中缓冲区的字符
最后执行结果为

BBBAABAA

(取决于两个进程执行的顺序)

Test3

if(fork() && fork())
    printf("A\n");
else
    printf("B\n");

该 if 块中第一个 fork() 生成一个子进程,返回 0,所以第二个 fork() 不会执行
父进程返回 pid,执行第二个 fork(),再次产生一个子进程
所以最终 printf 调用了三次,最后执行结果为

A
B
B

Test4

#include <stdio.h>
#include <stdlib.h>

// 测试栈空间的变量
void f0()
{
    int tmp = 0;
    int pid = fork();
    if(pid == 0)
    {
        tmp++;
        printf("son\n");
    }
    else if(pid > 0)
    {
        printf("parents\n");
    }
    else
    {
        return;
    }
    
    printf("%d\n",tmp);
}
 
 
int tmp1 = 5;
// 测试全局变量
void f1()
{
    int pid = fork();
    if(pid == 0)
    {
        tmp1++;
        printf("son\n");
    }
    else if(pid > 0)
    {
        printf("parents\n");
    }
    else
    {
        return;
    }
    
    printf("%d\n",tmp1);
}

// 测试堆区变量
void f2()
{
    int *tmp2 = (int*)malloc(sizeof(int));
    *tmp2 = 0;
    int pid = fork();
    if(pid == 0)
    {
        (*tmp2)++;
        printf("son\n");
    }
    else if(pid > 0)
    {
        printf("parents\n");
    }
    else
    {
        return;
    }
    
    printf("%d\n",*tmp2);
}

通过在 main 分别执行以上三个函数,输出中父进程与子进程打印的 tmp 值均不相同
可以发现,fork() 后生成新的子进程与父进程是相互独立的,拥有独立的 VMA