《操作系统进程模型》由会员分享,可在线阅读,更多相关《操作系统进程模型(6页珍藏版)》请在金锄头文库上搜索。
1、操作系统进程模型进程的相关概念进程是一个程序的一次执行,这是一个动态的过程,一个进程包括了程序计数器、寄存器和变量的当前值。在多道程序中有多个进程同时在运行,从概念上他们有各自的CPU,实际上是一个CPU在各个进程之间快速地切换。每个进程靠自己独有的程序计数器来控制自己的程序执行流程,实际的物理程序计数器只有一个,当某个进程获得物理CPU时它的逻辑程序计数器就被装入实际的程序计数器中。进程有其从创建到销毁的生命周期。进程存在的意义就是完成一定的任务,通常将进程分为前台进程和后台进程。前台进程负责与用户交互,如用户可以终端上输入命令启动程序;后台进程不与特定的用户关联,负责处理一些专用的事件,比
2、如监听网络端口的请求,后台进程又称为守护进程。进程完成它的工作后就自动退出,释放占用的系统资源。进程并不是在所有情况下都“自愿”退出的,它可能是由另外的进程杀死的,也可能是因为执行期间发生了严重错误被系统强制终止的。有些进程是被操作系统生成的,有些进程是由其他进程创建的(即父进程创建子进程)。在Minix和Linux系统中第一个用户进程init进程是由操作系统创建的,此后的所有进程都是init进程的子进程或孙进程。进程之间形成一种树状的层次结构。虽然每个进程都是一个独立的实体,有它自己的程序计数器、堆栈、打开的文件、定时器和内部状态,但进程之间还要进行交互、通信以及其他同步操作。由于进程之间要
3、相互依赖,同步执行,这就决定了进程从创建开始是很难一口气执行到底的,进程调度也要求进程中执行期间必须有间歇。大体上我们把进程的状态分为三种:运行态、就绪态和阻塞态。进程处于运行态是指它正在占用CPU。从运行态转入就绪态仅仅是因为处理机的调度策略使把正在执行的进程换出CPU,转而去执行其他进程,当调度策略又转回来时,处于就绪态的进程就可以立刻执行。从运行态转入阻塞态就由于进程缺少某种必须的资源,如程序要执行必须是等待用户参数的输入,当阻塞的进程获得这种资源后就转入就绪态,只要调度策略允许它随时可以执行。就像刚刚提到的那样,就绪队列中有多个进程时它们都可以马上运行,那么到底运行哪个呢?这是由调度器
4、来决定的。最简单最直观的调度算法是维持一个单一的就绪队列,谁先到达队列中谁先执行。在实际的系统中往往给进程分配一定的优先级,优先级高的进程虽然后到达就绪队列,但由于它要执行的事情紧急调度器可以让它先执行。系统中优先级数目是有限制的,我们只能把若干个进程统一规为一种优先级,在同一个优先级内部采用先到先运行的法则。为避免那些优先级别低的进程长时间等待甚至是“饿死”,操作系统还采用一定的策略来逐步降低执行频率高的进程的优先级。在操作系统中协作的进程间要对某块公共存储区进行读写,这个公共存储区可能在主存中(比如是一个内核数据结构),也可能是一个共享文件。由于进程何时运行何时休眠,基于什么时候产生、什么
5、时候终止都是无法预知的,那么不了的进程对同一存储区的读写顺序也是无法预知的,因此我们要有一种机制来实现进程间的同步。我们把不同进程共享的内存区称为临界区,当一个进程进入临界区后,其他进程必须在外面等待,同时还要选择一种策略使在临界区外面等的进程不能无限期的等下去,即要公平地为进程分配进入临界区的机会和时间。Minix进程模型系统结构Minix系统整体采用四层结构,如下图所示:图1. Minix四层结构内核负责进程的调度,并负责进程在运行态、就绪态和阻塞态之间切换。内核还负责进程间所有的通信消息,消息需要核实目标的合法性,定位内存中发送和接收的缓存区,并把消息从发送缓存复制到接收缓存。内核的另一
6、部分是支持对I/O端口和中断的访问。内核以上的其他三层统称为用户层,内核对这三层同等对待。它们都不直接对I/O进行操作,也不能访问分配给他们以外的内存。第2层设备驱动程序层可以请求系统任务任代表它们从I/O端口读数据或向I/O端口写入数据。第3层上是服务器进程,即向用户进程提供有用的服务。有两个服务必不可少:进程管理器和文件系统。进程管理器执行所有涉及启动或终止进程的Minix系统调用,如fork,exec,wait等,并负责执行与信号有关的系统调用,如alarm,kill。进程管理器还负责内存管理,如brk系统调用。文件系统负责执行文件的系统调用,如read,mount,chdir等。再生服
7、务器启动或重启那些不与内核一起加载到内存中的设备驱动程序。如果驱动程序在操作中失败,再生服务器检测到这一失败,并杀死这个驱动程序(如果它还没有死),重启这个驱动程序的一个新副本,从而提高操作系统的容错能力。第2层和第3层内的设备驱动程序和服务器统称为系统进程,它是操作系统的一部分,不属于某一特定用户,并且大部分在第一个用户登录前启动。第4层是所有的用户进程,如shell程序、编辑器、编译器、用户程序等。许多用户进程是随着用户的登录、工作、退出而创建和销毁的,而有些进程是从系统启动时创建并一直运行的。守护进程(daemon)是周期性地运行或一直等待某个事件的后台进程。进程的创建当硬盘启动Mini
8、x系统时,硬盘的第一个磁道第一个扇区512字节是一个主引导记录(MBR,master boot record),它包含了一段可执行程序的一个磁盘分区表。执行这段程序并读入分区表选择活动分区。活动分区的第一个扇区有一个引导程序,引导程序执行后启动boot程序。Boot程序找到引导镜像(Boot Image),并把引导镜像中的各个文件分装到内存的适当位置。引导镜像中几个重要的文件是内核、进程管理器、文件系统、再生服务器、Init进程等。Init进程作为第1个用户进程也是作为引导镜像的一部分加载的最后一个进程,它在系统运行期间一直存在。一个Minix用户启动多个shell,在shell里面执行自己的
9、进程,各个shell都是init的子进程,而用户进程则是init的孙进程,所有的用户进程都是同一棵进程树的组成部分。Fork系统调用是创建新进程的唯一途径,exec允许一个进程执行一个指定的程序。进程间通信Minix提供三条原语来发送和接收消息:send ( dest , 用来向进程dest发送一条消息,receive ( source , 用来接收一条来自进程source的消息,sendrec ( src_dst , 用来发送一条消息并等待同一个进程的应答。对于sendrec进程把消息发送出去后把自己阻塞等待应答,应答消息将覆盖原先的消息。有时候需要不阻塞的消息发送。notify(dest)
10、调用不阻塞的,即不管接收都是否正在等待消息,发送者都将继续执行。因为通知消息不阻塞,所以可以用它来避免死锁。进程调度Minix调度器拥有一个16级的排除系统。最低级别的是IDLE进程,用户进程启动时默认的优先级会比IDLE进程的优先级高一些。在Minix四层结构中,用户进程的优先级最低,服务器进程次低,驱动程序比前两者要高,而时钟和系统任务则处于最高的优先级别上。此外针对不同类别的进程它所分到的时间片(即进程在被抢占前所允许运行的最大时间间隔)也是不同的。用户进程拥有一个较小的时间片,驱动程序进程和服务器进程可以运行到阻塞,但它们是可强占的。当一个优先级高的进程超时运行时将把该进程放到一个较低
11、优先级队列的队尾,如果下一次这个进程又运行超时,那么它的优先级将再被降低一级。当然被降了级的进程其优先级也还是有机会得到提高的,这种情况发生在它用完了时间片但没有妨碍其他进程运行时。Linux进程模型进程结构Linux中每个进程被创建时都会拥有一个进程标识符(PID)。进程标识符不是进程在task向量表中的索引,而是032767之间的一个整数,在进程创建时动态生成。在Linux内核中有一个相当大的数据结构task_struct(在文件/usr/src/linux-headers-2.6.32-25 / include/linux/sched.h中)来描述进程,此结构中除了进程所必需的数据外,还
12、包含了大量其他的数据来统计和维护与其他进程的关系。我们不去细究task_struct的每一项,在Shell中输入ps -aux来查看当前所有已打开进程的相关信息:USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 921 2.2 2.1 29092 22248 tty7 Rs+ 09:58 0:54 /usr/bin/X :0 -root 928 0.0 0.0 1792 560 tty4 Ss+ 09:58 0:00 /sbin/getty -8 USRE项给出进程的属主,task_struct结构中有4对用户和组标识符:(1
13、)uid和gid运行该进程的用户ID和组ID,通常是进程创建者的uid和gid。(2)euid和egid有效uid和gid。(3)fsuid和fsgid文件系统uid和gid。(4)suid和sgid备份uid和gid。这是POSIX标准的要求。PID是进程标识符,%CPU代表该进程对CPU的占用率,%MEM是内存占用率,VSZ指出进程的虚拟内存大小,RSS是驻留中页的数量,TTY是终端ID。STAT是进程的状态。Linux可以使用以下状态:D-不可中断等待状态。进程在等待队列中,正在等待被唤醒。处于这种状态的进程只能显示被唤醒,不能被信号或中断自动唤醒。R-正在运行可或在就绪队列中,处于这种
14、状态的进程可以参与进程的调度。 S-可中断等待状态。处于等待队列中,正在等待某事件或资源。这种进程可以被信号或中断唤醒。T-暂停状态,可以再恢复。导致进程暂停的原因可分为两类:收到了SIGSTOP、SIGSTP、SIGTTIN、 SIGTTOU等信号;受到其他进程(如Debug进程)的追踪。系统调用ptrace可以停止被追踪的进程。Z-僵尸进程。在Linux进程的状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位 置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。它需要它的父进程来为它
15、收尸,如果他的父进程没安装 SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束,又没有显式忽略该信号,那么它就一直保持僵尸状态,如果这时父进程结束了, 那么init进程自动会接手这个子进程,为它收尸,它还是能被清除的。START是进程开始运行的时间,TIME是进程运行持续的时间,COMMAND是进程命令对应的文件。当调用ps lax还会看到进程有下面几个属性:PPID进程的父进程ID。NI-进程的NICE值,数值大,表示较少占用CPU时间。WCHAN进程等待的资源。进程调度Linux中进程调试都是非强占式的,系统采用相当简单的基于优先级的调试算法。进程只能在核心态等待,当
16、进程执行系统调用时它会从用户态“陷入”核心态,这时内核代表这个进程执行。当进程在核心态等待某事件时,系统会将它挂起,而后让另一个进程运行。Liunx的调度函数是schedule,定义在kernel/sched.c中。Schedule函数完成以下工作:(1)定义两个指针。prev是正在运行的进程,next是调度程序选择下一个将要运行的进程。这两个指针可能会相同。(2)处理调度任务队列。首先检查任务是否在队列中,如果有等待处理的任务则顺序处理其中的每一个任务,然后将队列清空。(3)检查任务是否在中断队列中,如果在,则不做本次调度,直接返回。(4)底半处理。就是中断处理的后半部分。(5)调度运行进程队列。与Minix不同的是Linux没有将可运行进程按其优先级分成多个队列,而是把系统中所有可运行进程(状态为TASK_RUNNING)都排在同一个队列中,这实际上是一个双向链表,如下图所示:图2. 运行进程队列当调度策略是SCHED_RR时,并且时间片已耗尽,则当前进程的时间片重新设置为它的优先级