进程创建 fork() 关于 代码共享,数据独有 的理解

2019-07-14 10:27发布

fork() 进程创建:
需要包含头文件:
fork( ) 通过复制调用进程(就是复制了PCB),创建一个新的进程(子进程)
子进程复制的就是父进程的PCB,(父子进程数据,代码看起来都一样)
复制PCB — 代码共享(子进程并非从头开始),数据独有
创建子进程的意义: 压力分摊 或 干其它事情
如何分辨子进程: 返回值
用返回值区分父子进程:
父进程返回的是子进程的PID
子进程返回的是0
我的程序因为父子进程代码运行一样,所以需要通过返回值来区分父子进程
源代码:
fork()进程创建
运行结果:
结果
在这里我们可以看到:
给定a值为100,父进程没有改变a的值,父进程中打印a的值依然是100;我们在子进程中改变a的值,子进程中打印的a值变为20.
这就是所谓的 “代码共享,数据独有
为了理解 “代码共享,数据独有” ,需要理解 写时拷贝技术 写时拷贝技术: 子进程拷贝了父进程的PCB和页表,当子进程中变量发生改变时,此时才会新开辟物理空间给子进程使用,并且改变页表到物理地址的映射关系(虚拟地址没变,但映射的物理地址已经变化)(写时拷贝技术就是说修改了才开辟空间和拷贝)
写实拷贝技术的优点: 节省资源,提高子进程创建效率
代码段是只读的,只读的访问控制由页表来控制
页表的作用: 1.记录虚拟地址与物理地址之前的映射关系 2.并且对地址进行内存访问控制 由于代码是只读的(不能修改),所以子进程和父进程指向的代码地址是相同的,则代码共享, 页表使得数据独有 理解了写时拷贝技术就不难理解为什么数据独有导致在父进程和子进程中a的值会有所不同
下面是我的理解:
通过 fork() 创建子进程时,子进程拷贝了父进程的PCB和页表,此时父子进程指向的代码地址是相同的,所以代码段共享;父子进程页表相同,所以虚拟地址相同(&a 都是 0x7ffcf0b81608),此虚拟地址通过页表映射到变量a的物理地址也相同;但当子进程中改变变量a的值的时候,通过写实拷贝技术(写时拷贝技术就是说修改了才开辟空间和拷贝)开辟一块新的物理空间给子进程使用,并将变量a的值拷贝到新的物理空间并改变其值为20,并且改变页表到物理地址的映射关系(虚拟地址没变,但映射的物理地址已经变化),解释到这里就不难理解以上的运行结果了.