如下的介绍方法是对应于实验中的3个部分进行分别说明,而对于这3个部分主要以分析代码的结构与流程来介绍,而对于细节的实现还需要去认真查看代码。本文只对核心的部分进行介绍,引导读者从基本的部分去学习与理解linux内核的部分代码。
一)进程管理:
在浩如烟海的代码中,如何寻找,太麻烦了。所以我们需要使用其他人的分析结果(参考了《深入理解Linux内核第3版》的部分章节),然后根据相关介绍去有针对性的查看代码。但是我们分析的对象是kernel4.0.2.跟原文中有些出入。当然对于去理解linux内核的程序员,当然这本书是不可多得的参考资料,但是实际使用的linux内核却是发展的,所以还是需要我们触类旁通的理解之。
根据实验3的内容我们首先需要找到对进程的抽象描述,即核心数据结构,由于其结构很是复杂,就不在博客中列出,而是放在附件的源码中。内核的核心数据结构为task_struct——include/linux/sched.h(1286)。当我们打开该数据结构时,第1感觉肯定是定义太复杂了,从什么地方入手呢?我们可以从两个方面入手去理解:其一为从经典的操作系统教程中找寻进程的描述,然后以之为切入点对应分析(可以参考的教程为《操作系统精髓与设计原理第6版》),其二为从简单的操作系统模型去把握核心的部分去分析,然后以此为基础去逐步扩展着分析。当然,我们介绍的是第2种方法,因为我们已经知道了一个简单的操作系统模型。
根据实验3的进程属性分析我们可以将进程属性分为如下几部分:
-
进程标识符(pid,stack)
内核有两种方式识别进程:其一为unix标准的id号(见结构体元素:pid_t pid);其二通过进程的描述符地址,每个进程都会分配唯一的一个进程描述符。对于进程id号,需要被循环使用,它被结构体pid_namespace(pid_namespace.h)中的pidmap所指向的page进行管理,用该页帧的每个bit位来表示已经使用的pid号。
对于进程描述符地址,因为进程描述符与每个进程是一一对应的,当内核需要对进程进行操作时,首先需要得到进程描述符地址,然后对其数据进行操作;对于此linux内核用了一种 巧妙的方式来进行操作,这种方式是基于每个进程在内核状态都有自己唯一的堆栈,将进程执行的必要状态(线程相关状态)