进程 = 内核数据结构 + 进程代码和数据!!
创建子进程,给子进程分配对应的内核结构,必须子进程自己独有了,因为进程具有独立性!理论上,子进程也要有自己的代码和数据。可是一般而言,我们没有加载的过程,也就是说,子进程没有自己的代码和数据! !所以,子进程只能”使用“父进程的代码和数据!!!!
代码:都是不可被写的,只能读取,所以父子共享,没有问题!
数据:可能被修改的,所以,必须分离!
回过来,我们就数据而言,在进程创建的时候,我们就需要进行数据的分离吗???
答案是不需要的,因为有可能子进程就不会用到数据空间,又有可能子进程就只是对数据进行读取操作,不会修改数据,所以创建子进程,不需要将不会被访问的,或者之只会读取的数据,拷贝一份。
作为OS,它也无法提前知道那些数据是需要进行读操作,哪些是进行写操作的???又或者提前拷贝了,我们不一定会立马使用。故整体上采用了写时拷贝的策略,来将父子进程的数据进行分离!!!
OS为啥选择写时拷贝技术,对父子进程进行分离
- 用的时候再给你进行分配,是高效使用内存的表现
- OS无法在代码执行前预测哪些空间会被访问??
这个写时拷贝 和 string 的深浅拷贝进行联系!!!!
fork之后,父子进程代码共享,是所有的代码共享,并不是after之后的!!!
注意,fork之后,谁先执行完全由调度器决定。
pc指针:程序计数器。
在Liunx中是CPU中的EIP。
当前正在执行的代码的下一行代码的地址!!
Linux中EIP中的值加上当前执行代码的长度就是下一句的地址。如果是函数跳转的话,就直接是那个的地址。
1.我们的代码汇编之后,会有很多行代码,而且每行代码加载到内存之后,都有对应的地址
2.因为进程随时可能被中断(可能并没有执行完),下次回来,还必须从之前的位置继续运行(不是最开始哦!),就要要求CPU必须随时记录下,当前进程执行的位置,所以,CPU内有对应的寄存器数据,用来记录当前进程的执行位置!
寄存器在CPU内,只有一份,寄存器内的数据,是可以有多份的!
创建的时候,要不要给子进程?
虽然父子进程各自调度,各自会修改EIP,但是已经不重要了,因为子进程已经认为自己的EIP起始值,就是fork之后的代码!!
寄存器的数据包括EIP的初始值都是进程的上下文数据