fork、写实拷贝、虚拟地址空间

1.fork

        我们在进程中使用fork函数,就会衍生出一个进程,我们去姑且称原本的进程为父进程,衍生出来的进程叫子进程,在下一篇文章会讲到我们可以用子进程做什么事情。

        在fork之前父进程单独执行,fork之后两个执行流分别进行,fork之后子进程执行fork之后的代码,这段代码父子共享,那么是否fork只执行fork之后的代码就意味着只共享这后面的代码?

        不是的,父子进程共享了所有的代码,只不过子进程只能从这里开始执行。这是怎么实现的呢?

        在cpu中有一个程序计数器eip,它会保存当前正在执行的指令的下一条指令。

        fork之后,eip程序计数器会拷贝给子进程,子进程便从该eip所指向的代码开始执行。

2.fork之后,os做了什么

        每个进程都有独立性,子进程是进程当然也具有独立性。

        首先,我们要知道进程=内核的进程数据结构+进程的数据和代码。

        那么,os在fork之后创建了子进程的进程的内核数据结构(struct mm_struct+struct task_struct+页表)+代码继承父进程,数据以写时拷贝的方式,来进行共享或者独立。

3.什么是虚拟地址空间

        每个进程都有自己独立的虚拟地址空间。

        什么是虚拟地址空间呢?其实就是os给进程画的大饼,让每一个进程都认为自己独占系统中的所有资源(内存)。

        为什么要画大饼,如实的让进程占有多好,反正内存那么大,

        为什么要有虚拟地址空间?

        ①.保护内存,直接让进程访问物理内存是不安全的,也许哪一个阿猫阿狗(野指针)非法访问内存,导致不属于进程的内存发生改变。

        ②.对进程和内存更好的管理,通过地址空间,进行功能模块的解耦。

        ③.让进程和程序已统一的视角去看待内存。方便以统一的方式来编译和加载所有的可执行程序。以简化程序的设计和实现。

        虚拟地址空间,在linux下是一个名为mm_struct的结构体来描述的。

        

        看着可高大上了吧,其实在mm_stuct这些区段都是由一个个区段的开始位置和结束位置所组成的。

struct mm_struct
{
    long code_start;
    long code_end;
    
    long heap_start;
    long heap_end;

    long stack_start;
    long stack_end;
    ...           
};

 4.上文的写时拷贝是什么?

我们来看下,进程到真正的物理内存要经过什么?

        通过页表映射到内存。

        父子进程都如图进行执行。

        写时拷贝,通常,父子进程共享代码,父子再不写入时,数据也是共享的,当一方试图写入时,编译以写时拷贝的方式拷贝一份出来,在另一处修改。在其他处修改,不会父或子进程的数据。

 

 

 为什么要写时拷贝?

1.避免浪费空间,子进程不一定要进行写入,如果不进行写入,却也拷贝出一个和父进程的代码数据一样的数据再占一块空间,纯属浪费空间。

2.理性情况下,在子进程进行写入时,进行分离拷贝。不修改则公用。

3.无脑拷贝会增加fork的成本(内存和时间)。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值