【Linux Kernel 进程管理】深入分析fork

来源:互联网 发布:c语言转汇编 编辑:程序博客网 时间:2024/06/05 04:08

这部分系列文章,从fork,vfork,clone三个系统调用入手,深入分析其过程,最后是总结和对比。每个系统调用可能需要好几篇文章,有空就来写写,希望能与各位互相交流学习。

首先是fork,很熟悉的一个系统调用,短短几行,一个“崭新”的进程就出现了。


 

一、 解释一下fork返回值: 返回两个值的概念和fork()的返回完全不同,例如return [res1,res2],而fork()真的只返回一个值:当前进程在当前命名空间的pid值。


为何出现返回两个值的幻觉,先简单说一下,函数的返回一般是通过寄存器例如eax。子进程创建成功后,会继续执行接下来的代码,父进程的eax写0,子进程的eax写pid,相当于两个进程分别读取各自的eax(这里的eax是虚拟给进程的,而不是真是的eax,毕竟eax只有一个),当然会有两个不同的值了。具体的细节以后遇到再阐述。

 

二、 fork,最终执行的内核函数是_do_fork(),这篇文章只介绍与fork相关的


可以看到,clone_flags只有SIGCHLD,这个信号是当子进程结束时,通知父进程的,如果父进程对SIGCHLD置之不理,就会产生僵尸进程。如果父进程结束,僵尸进程也会消失,不是因为他自觉消失了,而是用户态进程老大init完成了他父进程本该完成的工作。

三、_do_fork()


各种参数以后再说,因为fork只是把CIGCHLD标志位置1,其他参数都为空。

四、 首先申明需要的结构体指针,trace类型,和最后要返回的Pid值,很直观。


五、 fork的核心,copy 下一篇展开详细的分析。


六、 task_struc复制结束之后,设置trace,获取pid。


       主要是获取已经分配给子进程的PID实例,然后通过pid_vnr获取对应的pid数值,这

里有一点就是,对于PID实例,有get 和put操作肯定是成对出现的,get会增加此pid的引用计数,而put相反,用于内存回收,不然会造成内存泄漏。

七、子进程加入调度队列,fork返回。可以看到返回之前,子进程已经加入调度了,所以解释了为什么return的值不同

 


到此为止,整个fork就结束,看起来很简单,但是…水还很深,列举几个可能存在的疑问:

(1)     trace是干什么用的?

(2)     PID为什么是一个结构体,不应该是一个数值吗?

(3)     copy_process到底都做了什么事?

 这些问题每一个都能说好多,所以只能是慢慢来了,下一篇先展开copy_process。

原创粉丝点击