您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > 阅读Linux内核完全解释阅读报告
阅读Linux内核完全解释阅读报告一、任务目标:通过阅读LINUX0.11内核进程管理和控制部分的源码,进一步了解LINUX操作系统进程管理的实现原理,掌握进程管理的主要概念和主要进程控制功能的实现方法。二、阅读内容:阅读Linux内核完全解释中的fork.c,sched.c和exit.c中主要功能函数三、问题及回答:1.Linux0.11如何管理内核任务和用户任务的?内核任务和用户任务包含的主要信息有哪些?这些信息的主要作用是什么?(1)利用分时技术,在Linux操作系统上同时可以运行多个进程。对于Linux0.11内核来讲,系统最多可有64个进程同时存在。除了第一个进程用“手工”建立以外,其余的都是现有进程使用系统调用fork创建的新进程,被创建的进程称为子进程(childprocess),创建者,则称为父进程(parentprocess)内核程序使用进程标识号(processid,pid)来标识每个进程。进程由可执行的指令代码、数据和堆栈区组成。进程中的代码和数据部分分别对应一个执行文件中的代码段、数据段。每个进程只能执行自己的代码和访问自己的数据及堆栈区。进程之间的通信需要通过系统调用来进行。内核通过调度程序分时调度各个进程运行。Linux系统中一个进程可以在内核态(kernelmode)或用户态(usermode)下执行,并且分别使用各自独立的内核态堆栈和用户态堆栈。用户堆栈用于进程在用户态下临时保存调用函数的参数、局部变量等数据:内核堆栈则含有内核程序执行函数调用时的信息。从对中断机制的说明可知,用户程序通过直接或间接(通过库函数)调用中断int0x80,并在eax寄存器中指定系统调用功能号,即可使用内核资源,包括系统硬件资源。不过通常应用程序都是使用具有标准接口定义的C函数库中的函数间接地使用内核的系统调用。内核程序通过进程表对进程进行管理,每个进程在进程表中占有一项。在Linux系统中,进程表项是一个taskstruct任务结构指针。称其为进程控制块PCB(Processcontrolblock)或进程描述符PD(Processordescriptor)。其中保存着用于控制和管理进程的所有信息。主要包括进程当前运行的状态信息、信号、进程号、父进程号、运行时间累计值、正在使用的文件和本任务的局部描述符以及任务状态段信息。(2)核任务和用户任务包含的主要信息有任务执行空间、任务状态段TSS、TSS描述符、任务寄存器TR、任务门描述符、标志寄存器EFLAGS中的NT标志、任务地址(物理地址和逻辑地址)空间。(3)TSS在任务切换过程中起着重要作用,通过它实现任务的挂起和恢复。所谓任务切换是指,挂起当前正在执行的任务,恢复或启动另一任务的执行。在任务切换过程中,首先,处理器中各寄存器的当前值被自动保存到TR所指定的TSS中;然后,下一任务的TSS的选择子被装入TR;最后,从TR所指定的TSS中取出各寄存器的值送到处理器的各寄存器中。由此可见,通过在TSS中保存任务现场各寄存器状态的完整映象,实现任务的切换。2.在Linux0.11中,创建一个新进程的主要任务包含哪些?主要流程是什么?在Linux中创建一个新进程的方法是使用fork函数,fork()执行一次但有两个返回值。在父进程中,返回值是子进程的进程号;在子进程中,返回值为0。因此可通过返回值来判断当前进程是父进程还是子进程。使用fork函数得到的子进程是父进程的一个复制品,它从父进程处复制了整个进程的地址空间,包括进程上下文,进程堆栈,内存信息,打开的文件描述符,信号控制设定,进程优先级,进程组号,当前工作目录,根目录,资源限制,控制终端等。而子进程所独有的只是它的进程号,资源使用和计时器等。可以看出,使用fork函数的代价是很大的,它复制了父进程中的代码段,数据段和堆栈段里的大部分内容,使得fork函数的执行速度并不快。fork首先会为新进程申请一页内存页用来复制父进程的任务数据结构(PCB)信息,然后会为新进程修改复制的任务数据结构的某些字段值,包括利用系统调用中断发生时逐步压入堆栈的寄存器信息(即copyprocess)的参数)重新设置任务结构中的TSS结构的各字段值,让新进程的状态保持父进程即将进入中断过程前的状态。然后为新进程确定在线性地址空间中的起始位置(nr*64MB)。对于CPU的分段机制,Linux0.1l1的代码段和数据段在线性地址空间中的位置和长度完全相同。接着系统会为新进程复制父进程的页目录项和页表项。对于Linux0.1l1内核来说,所有程序共用一个位于物理内存开始位置处的页目录表,而新进程的页表则需另行申请一页内存来存放。在fork的执行过程中,内核并不会立刻为新进程分配代码和数据内存页。新进程将与父进程共同使用父进程已有的代码和数据内存页面。只有当以后执行过程中如果其中有一个进程以写方式访问内存时被访问的内存页面才会在写操作前被复制到新申请的内存页面中。3.在Linux0.11中设置了哪些进程状态?进程状态之间是如何转换的?设置僵尸状态的目的是什么?◆运行状态(TASK_RUNNING)当进程正在被CPU执行,或已经准备就绪随时可由调度程序执行,则称该进程为处于运行状态(running)。进程可以在内核态运行,也可以在用户态运行。当系统资源已经可用时,进程就被唤醒而进入准备运行状态,该状态称为就绪态。这些状态(图中中间一列)在内核中表示方法相同,都被成为处于TASK_RUNNING状态。◆可中断睡眠状态(TASK_INTERRUPTIBLE)当进程处于可中断等待状态时,系统不会调度该进程执行。当系统产生一个中断或者释放了进程正在等待的资源,或者进程收到一个信号,都可以唤醒进程转换到就绪状态(运行状态)。◆不可中断睡眠状态(TASK_UNINTERRUPTIBLE)与可中断睡眠状态类似。但处于该状态的进程只有被使用wake_up()函数明确唤醒时才能转换到可运行的就绪状态。◆暂停状态(TASK_STOPPED)当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可运行状态。在Linux0.11中,还未实现对该状态的转换处理。处于该状态的进程将被作为进程终止来处理。◆僵死状态(TASK_ZOMBIE)当进程已停止运行,但其父进程还没有询问其状态时,则称该进程处于僵死状态。当一个进程的运行时间片用完,系统就会使用调度程序强制切换到其它的进程去执行。另外,如果进程在内核态执行时需要等待系统的某个资源,此时该进程就会调用sleep_on()或sleep_on_interruptible()自愿地放弃CPU的使用权,而让调度程序去执行其它进程。进程则进入睡眠状态(TASK_UNINTERRUPTIBLE或TASK_INTERRUPTIBLE)。只有当进程从“内核运行态”转移到“睡眠状态”时,内核才会进行进程切换操作。在内核态下运行的进程不能被其它进程抢占,而且一个进程不能改变另一个进程的状态。为了避免进程切换时造成内核数据错误,内核在执行临界区代码时会禁止一切中断。4.在Linux0.11中,进程调度考虑了哪些因素?你还能提出新的调度策略吗?1)在gdt中设置ldt、gdt:ldt和gdt的定义在sched.h中。2)将eflags中的NT置位:记得在前面关于任务切换的说明中,我提到在main的中sched_init()之后,调用move_to_user_mode()实现核心态到用户态的转换,而在move_to_user_mode()中,最后调用了iret,如果将NT为0,就不会引起进程的切换了。3)加载tss和ldt:手动加载仅这一次,以后都是通过任务的切换CPU自动加载的。在这里,因为是第一个用户任务,所以需要手动设置。4)初始化8253定时器。5)在IDT中设置时钟的中断门和系统调用的中断门。6)调用switch_to()函数,它能实现任务的切换,它的定义在sched.h中,主要原理就是利用如果ljmp的操作数是任务门描述符就会引起任务的切换。7)等待队列。等待队列其其实就是一个进程指针链表,所有由于等待同一个资源的睡眠进程组成一个等待队列。8)唤醒wake_up(),将等待队列的头进程的状态置成就绪态。5.进程上下文主要指什么?主要包含哪些信息?进程切换是如何实现的?当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中继服务结束时能恢复被中断进程的执行。为了控制进程的执行,内核必须有能力挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行,这叫做进程切换、任务切换、上下文切换;即进程上下文切换。进程被抢占CPU时候,操作系统保存其上下文信息,同时将新的活动进程的上下文信息加载进来,这个过程其实就是上下文切换,而当一个被抢占的进程再次成为活动的,它可以恢复自己的上下文继续从被抢占的位置开始执行.上下文切换(有时也称做进程切换或任务切换)是指CPU从一个进程或线程切换到另一个进程或线程。挂起一个进程,将这个进程在CPU中的状态(上下文)存储于内存中的某处,在内存中检索下一个进程的上下文并将其在CPU的寄存器中恢复跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程。因此上下文是指某一时间点CPU寄存器和程序计数器的内容,广义上还包括内存中进程的虚拟地址映射信息.最后用switch_to完成了进程的切换,该函数切换了寄存器状态和栈,新进程在该调用后开始执行,而switch_to之后的代码只有在当前进程下一次被选择运行时才会执行。执行环境的切换是在switch_to()中完成的,switch_to完成最终的进程切换,它保存原进程的所有寄存器信息,恢复新进程的所有寄存器信息,并执行新的进程。
本文标题:阅读Linux内核完全解释阅读报告
链接地址:https://www.777doc.com/doc-3619652 .html