第九周的实验依旧和往常的一样,主要包括两部分。一是1.阅读学习教材「Linux内核设计与实现 (Linux Kernel Development)」第教材第13,14章。二是学习MOOC「Linux内核分析」第七讲「Linux内核的实质和Linux系统的一般执行过程」,并完成实验楼上配套实验。
然后我们开始这周的实验,首先通过本科的一些学习操作系统中的进程调度算法,但这些算法只是在选择的过程中用了不同的策略而已,对于理解操作系统的工作机制,反而是进程的调度时机与进程的切换机制更为关键。而我们接下来就去了解进程的调度机制和切换机制。 进程调度的时机•中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule() •内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度 •用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。进程的切换
•为了控制进程的执行,内核必须有能力挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行,这叫做进程切换、任务切换、上下文切换;•挂起正在CPU上执行的进程,与中断时保存现场是不同的,中断前后是在同一个进程上下文中,只是由用户态转向内核态执行;•进程上下文包含了进程执行需要的所有信息 •用户地址空间:包括程序代码,数据,用户堆栈等 •控制信息:进程描述符,内核堆栈等 •硬件上下文(注意中断也要保存硬件上下文只是保存的方法不同)•schedule()函数选择一个新的进程来运行,并调用context_switch进行上下文的切换,这个宏调用switch_to来进行关键上下文切换 •next = pick_next_task(rq, prev);//进程调度算法都封装这个函数内部 •context_switch(rq, prev, next);//进程上下文切换 •switch_to利用了prev和next两个参数:prev指向当前进程,next指向被调度的进程.
不同类型的进程又不同的调度需求。
第一种分类: -I/O-bound 1.频繁的进行I/O 2.通常会花费很多时间等待I/O操作的完成 -CPU-bound 1.计算密集型 2.需要大量的CPU时间进行运算 第二种分类 -批处理进程 1.不必与用户交互,通常在后台运行 2.不必快速响应 3.典型的批处理程序:编译程序,科学计算 -实时进程 1.有实时需求,不应被低优先级的进程阻塞 2.响应时间要短,要稳定 3.典型的实时进程:视频/音频,机械控制等 -交互式进程 1.需要经常与用户交互,因此要花很多时间等待用户输入操作 2.响应时间要快,平均延迟要低于10~150ms 3.典型的交互式程序:shell,文本编辑程序,图形应用程序等schedule()函数负责调度程序.
这里分析其中最简单也是最复杂的命令---ls1.在控制台下输入ls命令->为什么我们敲击键盘就会在终端上显示? 这里涉及到I/o终端,我们敲击后会形成一个I/o中断,系统会把当前运行的程序给中断了,然后需要在控制台上打印我们需要的信息。 2.shell程序分析输入参数,确定这是什么命令->什么是shell->终端解释程序 3.调用系统调用fork生成一个shell本身的拷贝->什么是系统调用? 内存保护,内核态用户态的相关问题。系统调用时怎么实现的?软中断,异常的概念。陷阱门,系统门。 fork是什么?为什么要调用fork?进程的描述,进程的创建。cow技术(写时复制技术)。 4.调用exec系统调用将ls的可执行文件装入内存。->内存管理模块,进程的地址空间,分页机制,文件系统,可执行文件格式如ELF。 5.系统调用返回->返回的位置,如何做到正确的返回,修改了exec的系统调用。 堆栈的维护,寄存器的保存与恢复。 6.shell和ls都得以执行->进程的调度,运行队列等待队列的维护。第二部分是关于课本知识的掌握。第十三章的虚拟文件系统,Unix使用了四种和文件系统相关的传统抽象概念:文件,目录项,索引节点和安装点。 VFS中有四个主要的对象类型,他们分别是:
1.超级块对象,它代表一个具体的已安装文件系统。 2.索引节点对象,它代表一个具体文件。 3.目录项文件,他代表一个目录项,是路径的一个组成部分。 4.文件对象,他代表由进程打开的文件。目录项对象有三种状态:被使用,未被使用和服状态。 目录项缓存包含三个主要部分: 1.“被使用的”目录项链表。该链表通过索引节点对象中的I_dentry项连接相关的索引节点,因为一个给定的索引节点可能有多个链接,所以就可能有多个目录项对象,因此用一个链表来链接他们。 2.“最近被使用的”双向链表。该链表含有未被使用的和负状态的目录项对象。 3.散列表和相应的散列函数用来快速地将给定路径解析为相应目录项对象。 第十三章主要讨论了各种数据结构,包括最重要的索引节点,目录项以及超级块对象。第十四章学习了块设备的相关知识,i/o层所用的数据结构:bio,表示活动的I/O擦皮做;buffer——head,表示块到页的映射:还有请求结构,表示具体的I/o请求。 心得体会: 学了这么长时间的Linux,对linux的操作,应用以及内部应用的运行过程有了一个清晰的认识,在以后的学习中,要利用学习Linux时的方法,有些东西光看了不行,还需要动手去做,在实践中发现问题并解决问题。这样才能有长足的进步。