北大操作系统高级课程-陈向群作业-XV6进程线程 联系客服

发布时间 : 星期日 文章北大操作系统高级课程-陈向群作业-XV6进程线程更新完毕开始阅读07c61910ec3a87c24128c464

阅读代码:

1. 基本头文件:

types.h param.h memlayout.h defs.h x86.h asm.h mmu.h elf.h

2. 进程线程部分:

vm.c proc.h proc.c swtch.S kalloc.c

以及相关其他文件代码

强调一下:由于内存管理部分还没有学到,所以请同学们遇到相关的代码和问题时,先将问题记录下来,到学过之后,再结合进程线程管理部分进行深入学习,最后要求对XV6有整体的理解。

请大家围绕如下一些问题阐述原理课的相关内容,以及XV6中是如何实现的。

1. 什么是进程,什么是线程?操作系统的资源分配单位和调度单位分别是什么?XV6中的

进程和线程分别是什么,都实现了吗?

答:进程是在多道程序系统出现以后,为了描述系统内部各作业的活动规律而引进的概念。进程有3个基本状态,运行状态、就绪状态和等待状态(或称阻塞状态);进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系;挂起命令可有进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的独立单位。

线程可称为轻量级的进程,是操作系统可以运行调度的最小单位。线程是进程内的一个相对独立的可执行的单元。若把进程称为任务的话,那么线程则是应用中的一个子任务的执行。

不论操作系统中是否引入了线程,操作系统中资源分配的基本单位都是进程。如果操作系统没有引入线程那么进程就是调度的基本单位。线程并不独立拥有资源,它仅仅分配了一些运行必备的资源。一个进程中的多个线程共同分享进程中的资源。在引入了线程的操作系统中,线程就变成了调度的基本单位,进程中的部分线程阻塞并不代表该线程被阻塞。

xv6操作系统实现了一个基于进程(没有实现线程)的简单进程管理机制。通过对proc.h文件的阅读了解到xv6的进程中定义了一个context结构,一个枚举类型proc_state定义了UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE 这6种进程的状态,proc结构定义了进程控制块的内容,cpu结构定义了寄存器和栈指针。

2. 进程管理的数据结构是什么?在Windows,Linux,XV6中分别叫什么名字?其中包含哪

些内容?操作系统是如何进行管理进程管理数据结构的?它们是如何初始化的? 答:进程管理的数据结构是进程控制块(PCB)。在Linux中进程控制块的结构是由一个叫task_struct的数据结构定义的,ask_struct存在/include/ linux/sched.h中,其中包括管理进程

所需的各种信息。在创建一个新进程时,系统在内存中申请一个空的task_struct区,即空闲PCB块,并填入所需信息。同时将指向该结构的指针填入到task[]数 组中。当前处于运行状态进程的PCB用指针数组current_set[]来指出。这是因为Linux支持多处理机系统,系统内可能存在多个同时运行的进 程,故current_set定义成指针数组。Windows 的进程由执行体进程块EPROCESS表示,EPROCESS即执行体进程对象。在Windows 中,PCB也称为内核进程块KPROCESS(KPROCESS即内核进程对象)EPOCESS和KPROCESS位于内核空间,PEB位于用户空间。XV6的进程控制块是proc类中的proc定义了进程ID,进程状态,父进程,context保存寄存器为内核的上下文切换,cpu记录了内存地址和栈指针等。XV6中通过proc.cc对进程进行控制管理,get_raw_proc()方法可以创建一个新的进程并对进程进行初始化分配进程页表和内核堆栈。

3. 进程有哪些状态?请画出XV6的进程状态转化图。在Linux,XV6中,进程的状态分别包

括哪些?你认为操作系统的设计者为什么会有这样的设计思路?

答:XV6进程包括UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE这6种状态即未使用态、初始态、等待台、就绪态、运行态、僵尸态。状态转换图如下:

UNUSED EMBRYO RUNNABLE ZOMBIE RUNNING SLEEPING

之所以这样设计是为了实现多道程序的交叉运行,和方便设计各种进程调度算法。在时间片轮转调度算法中RUNNING的程序在时间片到的时候就会转成RUNNABLE同时让出CUP。而正在EUNNING的程序如果遇到资源申请,就会主动放弃CPU进入SLEEPING状态。但是SLEEPING状态的程序如果得到资源之后并不能马上进入RUNNING而是先进入就绪队列等待CUP调度。

Linux的进程状态可分为R (TASK_RUNNING),可执行状态,S (TASK_INTERRUPTIBLE),可中断的睡眠状态,D (TASK_UNINTERRUPTIBLE),不可中断的睡眠状态,T (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态,Z (TASK_DEAD - EXIT_ZOMBIE),退出状态,进程成为僵尸进程,X (TASK_DEAD - EXIT_DEAD),退出状态,进程即将被销毁。

4. 如何启动多进程(创建子进程)?如何调度多进程?调度算法有哪些?操作系统为何要

限制一个CPU最大支持的进程数?XV6中的最大进程数是多少?如何执行进程的切换?什么是进程上下文?多进程和多CPU有什么关系?

答:子进程都是由父进程创建的,比如使用fork()函数。创建的过程为 1).为子进程分配一个空闲的proc结构(进程描述符) 2).赋予子进程唯一标识pid

3).以一次一页的方式复制父进程地址空间(有什么问题?)

4).获得子进程继承的共享资源的指针,如打开的文件和当前工作目录 5).子进程就绪,加入调度队列

6).对子进程返回标识符0;向父进程返回子进程pid

处理机调度可分为三个层次:长程调度、中程调度、短程调度。

长程调度(作业调度或宏观调度):创建新进程时 是否进入当前活跃进程集合。

中程调度涉及进程在内外存间的交换,从负载控制的角度,把一些进程换出到外存上,可为其他进程的执行提供所需内存空间,如需要再换入到内存。

短程调度(微观调度):从CPU分配的角度,需要经常选择就绪进程或线程进入运行状态,短程调度的时间尺度通常是毫秒级的。由于短程调度算法的频繁使用,要求在实现时做到高效。

常见的调度算法有:先来先服务、优先级调度算法、短作业优先算法、最短剩余时间优先算法、时间片轮转算法、高响应比优先算法、多级反馈队列算法。

XV6的最大进程数写在param.h文件中的#define NPROC 64 属性中。可以看出XV6默认定义的最大进程数是64。

进程切换是一个进程让出处理器,由另一个进程占用处理器的过程。 进程的切换是由进程状态的变化引起的,而进程状态的变化又与出现的事件有关。当有事件(中断或异常)发生时,当前运行进程暂停,由操作系统处理出现相应事件。处理结束,某些进程的状态会发生变化,因此,要调整队列。之后,进程调度根据调度算法从就绪队列选一个进程占用CPU。这个进程可能仍然是被中断的进程,也可能是另一个进程。

进程的上下文包括当前进程的程序计数器PC和当前运行的CPU中各个寄存器的内容。当进程切换和发生中断的时候这些信息要保存下来以便于下次运行时使用。

多进程和多CPU我理解他们的区别就是并发和并行的区别。多进程是并发执行,就是在一个时间段内有多个进程在执行,但是在某个时间点上是只有一个进程执行。

5. 内核态进程是什么?用户态进程是什么?它们有什么区别?

答:多数系统将处理器工作状态划分为内核态和用户态。前者一般指操作系统管理程序运 行的状态,具有较高的特权级别,又称为特权态、系统态或管态;后者一般指用户程序运 行时的状态,具有较低的特权级别,又称为普通态、目态。如果操作系统允许用户对计算机做任何操作都可以的话,我们的计算机一天死N次机都不足为奇。区分了用户态和内核态就是限定用户什么操作可以做,什么操作不能让用户直接做。如果遇到不能让用户直接做的操作,用户就必须请求操作系统做系统调用,这样操作系统就会进入内核态进行系统操作。内核态的进程就是系统进入内核态之后进行系统操作所产生的进程。而用户态进程是用户通过请求操作而产生的进程。它们的主要区别有:1).运行在不同的系统状态,用户态进程执行在用户态,内核态进程执行在内核态。2).进入的方式不同用户态进程直接进入而内核态必须通过运行系统调用命令。3).返回方式不同,用户态进程直接返回,内核态进程有重新调度过程。4).内核态进程优先级要高于用户态进程。并且内核态进程特权级别最高,它可以执行系统级别的代码。

6. 进程在内存中是如何布局的,进程的堆和栈有什么区别? 答:内存分为内核空间和用户空间,内核空间一般运行操作系统程序而用户空间一般运行用户程序。主要目的是对系统程序进行包含。进程在内存中包含堆、栈、数据段、代码段。 代码段:保存程序的执行码。在进程并发时,代码段是共享的且只读的,在存储器中只需有一个副本。

数据段:此段又称为初始化数据段,它包含了程序中已初始化的全局变量、全局静态变量、局部静态变量。

栈:程序执行前静态分配的内存空间,栈的大小可在编译时指定,Linux环境下默认为8M。栈段是存放程序执行时局部变量、函数调用信息、中断现场保留信息的空间。程序执行时,

CPU堆栈段指针会在栈顶根据执行情况进行上下移动。

堆:程序执行时,按照程序需要动态分配的内存空间。malloc、calloc、realloc函数分配的空间都在堆上分配。

其他要求,请同学们

1. 独立完成,不要抄袭;

2. 字数大约2000-3000字,不要粘贴大量代码; 3. 可以就其中一个你感兴趣的问题进行深入论述,不一定全部答完,但是要有自己的理解; 4. 可结合多种操作系统(windows,linux)的实现来进行问题说明。