这篇文章主要通过一些题目来巩固一些基础知识,熟悉一些底层原理
先来放一些基础,再来一些题目吧
PCB存放
每当我们创建一个新进程,有很多信息都需要记录,比如PID,权限,用户组,进程之间的关系,进程状态等等,他们都将被保存在一个数据结构当中,叫做task_struct,就是Process Control Block。
我们所谓的PCB主要存在了内核中,内核通过控制PCB来达到控制进程。
写时复制技术copy-on-write
内核只为新生成的进程分配虚拟空间,而物理空间会与父进程共同享用,但某一个线程真正要修改时,才会复制对应的页面内容,并在子线程开启自己的物理页面,并修改虚拟空间与物理空间映射关系。
原因
当父进程创建子进程时,我们如果把父进程的物理空间完完整整复制过去,各种映射关系,页面内容,只会使得效率低下,所以我们如果把页面标记为可读,那么一旦父进程或者某个子进程修改了某一个内容,就可以copy到自己的物理空间,使数据分离。
而且,在可读范围的访问之内,父进程或者子进程的某个物理地址如果被缓存在了TLB,如果另一个进程访问了这个物理地址,那么也可以很快的得到自己想要的结果,包括L1,L2各种数据缓存,进程之间在可读范围内都可以共享,而如果直接复制并开辟自己物理内存,那么必须重新去内存获取对应页的内容,甚至可能要去交换文件获取自己的页内容,那就真的太浪费时间了吧,还浪费空间。
fork函数
fork调用后,内核会为子进程分配对应的虚拟内存空间,同时它的正文段,数据段,堆栈端都是指向了父进程的物理空间,实现物理空间共享,并且内容可读,一旦某个进程修改这个共享的物理空间的内容,就会复制到子线程自己的物理空间。
我们知道虽然物理空间是共享的,但是PCB还是不能共享,内核还是会在内核区中分配给PCB一部分空间,这样内核就可以通过控制PCB来调度进程。
如上图一样,返回的情况有三种情况,如果成功的话在父进程返回自己成的PID,子进程返回0
1:首先内核就需要在内核区中分配一定大小的空间,存储PCB还有新进程的内核栈
2:将父进程PCB完整copy给子进程PCB,两个进程PCB是完全一样的
3:需要将子进程的状态设置为不会马上运行,因为它还需要资源建立
4:需要将继承过来PCB中的各种域更新一下,比如亲属关系,不可能爸爸的爸爸还是自己的爸爸吧
5:将进程插入到进程链表和哈希表(这是进程存放方式),然后将子进程设置为可运行状态。
6:子进程和父进程平分剩余时间片
7:返回子进程PID,由父进程获取
wait函数
函数功能是:
父进程一旦调用了wait就立即阻塞自己&#x