进程 --fork() 初步探究 及写时复制

COW技术初窥:

     在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。

      那么子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢?

      在fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。      

      在网上看到还有个细节问题就是,fork之后内核会通过将子进程放在队列的前面,以让子进程先执行,以免父进程执行导致写时复制,而后子进程执行exec系统调用,因无意义的复制而造成效率的下降。


未执行exec 父子进程共享代码段、数据段、堆栈段, 但执行写入能力时,内核给子进程数据段、堆栈段分配相应的物理空间,而代码段继续共享,若是执行exec 之后,子进程的代码段也会分配单独的物理空间。

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

#include <fcntl.h>          /* For O_* constants */
#include <sys/stat.h>       /* For mode constants */
#include <semaphore.h>


#define SEM_NAME "mysem"

#define FILE_MODE (0400 | 0200) 

int a = 2;

/*void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);*/


int main(int argc, const char *argv[])
{
    pid_t pid;
    sem_t *mutex;

    int i = 2;   
    
    if ((pid = fork()) == 0)
    {   
        i = 10; 
        a = 10; 
        printf("Child: i = %d\n", i); 
        printf("Child: a = %d\n", a); 
    }   
    else if (pid > 0)
    {   
        i = 20; 
        a = 20; 
        printf("parent inter: i = %d\n", i); 
        printf("parent inter: a = %d\n", a); 
    }   

    printf("parent outer: i = %d\n", i); 
    printf("parent outer: a = %d\n", a); 

    waitpid(-1, NULL, 0); 

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值