分享

fork和vfork那些事

 studydoer 2020-09-01

fork和vfork那些事

vfork:

#include <stdio.h>
#include <sched.h>
#include <unistd.h>

int data = 10;
int child_process(){
    printf("Child process %d, data1 %d\n",getpid(),data);
    data = 20;
    printf("Child process %d, data2 %d\n",getpid(),data);
    _exit(0);
}
int main(int argc, char* argv[]){
    if(vfork()==0) {
        child_process();
    }else{
        sleep(1);
        printf("Parent process %d, data3 %d\n",getpid(), data);
    }
}

你知道上述data1、data2和data3分别是多少吗?先自己思考下,后文一起解密。

fork:

#include <sched.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int data = 10;
int child_process(){
    printf("Child process %d, data4 %d\n",getpid(),data);
    data = 20;
    printf("Child process %d, data5 %d\n",getpid(),data);
    _exit(0);
}
int main(int argc, char* argv[]){
    int pid;
    pid = fork();
    if(pid==0) {
        child_process();
    }else{
        sleep(1);                           printf("Parent process %d, data6 %d\n",getpid(), data);
        exit(0);
    }
}

上述代码改动了一个地方,就是把vfork换成了fork,你知道data4、data5和data6的结果吗?我们先来分析下vfork和fork的区别,然后再公布答案。

先说fork吧。fork创建出子进程后,子进程复制了父进程的资源,诸如文件系统,打开的文件,信号等,但是内存空间却是用了写时拷贝机制(Copy On Write),简单介绍下写时拷贝机制,就是子进程拷贝父进程的页表,并将父进程中具有写权限的物理页对应的页表项置为只读,也就是说,此时父子进程具有相同的页表,虚拟地址对应的物理地址也一样,只是物理地址都是只读的,当子进程或父进程其中的一个写物理内存时,由于是只读的,所以会发生pagefault,此时才给执行写操作的进程分配物理页,并将新分配的物理页连接到执行写操作的进程的页表中,最后把旧物理页对应的在没执行写操作的进程的页表项改为可写。这样一来,父子进程相同的虚拟地址就对应了不同的物理地址。看完上述的分析,那么data4、data5和data6分别是10、20和10.你答对了吗?

再说vfork。vfork创建出子进程后,子进程复制了父进程的文件系统、打开的文件、信号等资源,但是内存空间却是与父进程共享的,且父进程会阻塞,直到子进程执行exit(0)或执行exec。由于共享内存,所以data1、data2和data3的值就是10、20和20.

最后在说一点,我们从分析中也可看出,fork是依赖Copy On Write机制的,而写时拷贝机制依赖MMU,所以在没有MMU的CPU上,就没有fork,但是可以有vfork。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多