1第六章Linux进程与存储管理234Linux的品牌•1.RedhatfedoraRedhat是最成功的一个发行版,它现在占住服务器领域,不过fedora计划了它的成功,用户群NO1。•2.DebianUbuntu:它非常的新,默认安装可以支持很多设备,如蓝牙,无线网络。•3.Suse:被NOVELL收购后开发出最拉风的系统,可以支持下一代3D桌面,性能更强,比WindowsVista3D更眩。•4.KNOPPIX:无需安装的光盘系统基于Debian,对显卡兼容性很强(用fbdev驱动),它最先提供64位支持。•5.MagicLinux:中文化最好的Debian发行版。•6.Debian发行版:最稳的系统(最老)。•7.gentoo:系统很紧筹,对软件包一类问题解决得很好,同样它也有无需安装的光盘版。•8.Lfs:可以从无到有Diy一个容入自己个性的Linux.其它Linux系统好比饭馆里的可口菜肴,Lfs给你的是做菜的秘方,每个人可以跟据它作出适合自己口味的美味Linux。5UNIX与LINUX•Linux和UNIX的最大的区别是,前者是开放源代码的自由软件,而后者是对源代码实行知识产权保护的传统商业软件。这应该是他们最大的不同,这种不同体现在用户对前者有很高的自主权,而对后者却只能去被动的适应;这种不同还表现在前者的开发是处在一个完全开放的环境之中,而后者的开发完全是处在一个黑箱之中,只有相关的开发人员才能够接触的产品的原型。•另外两大区别:1)UNIX系统大多是与硬件配套的,而Linux则可运行在多种硬件平台上.2)UNIX是商业软件,而Linux是自由软件,免费、公开源代码的.6内容•Linux进程管理•Linux存储管理7Linux进程管理•进程组成•进程环境•进程管理内容•进程控制块•进程状态•进程调度•进程控制•进程通信8进程组成Linux是一个多任务多用户操作系统,采用进程模型。进程都具有一定的功能和权限,运行在各自独立的虚拟地址空间,彼此独立,且通过通信机制实现同步互斥,通过调度程序实现合理调度。9进程组成正文段存放进程要运行的程序,描述了进程要完成的功能用户数据段存放正文段在执行时所需要的数据和工作区系统数据段存放了进程的控制信息,其中最重要的数据结构是task_struct。进程组成10进程环境Linux进程有两种状态:内核态和用户态核心态又称系统态Linux在执行内核程序时是处于核心态下用户态是进程的普通执行状态一个进程在运行过程中,总是在两种执行状态之间不断地转换。11进程虚拟地址空间分为:用户空间和系统空间。用户空间用户进程本身的程序和数据(可执行映象)进程运行用户程序时使用的堆栈,即进程堆栈。系统对进程进行控制和管理的信息,如进程控制块等系统空间内核被映射到所有进程的系统空间中。只允许进程在核心态下访问。进程运行在用户态下时,不允许直接访问系统空间。进程只能通过系统调用转换为核心态后,才能访问系统空间进程环境12进程环境进程上下文系统提供给进程处于动态变化的运行环境总和称为进程上下文系统上下文系统完成自身任务时的运行环境称为系统上下文内核在系统上下文中执行时不会阻塞。1314进程管理内容进程管理由进程控制块、进程调度、中断处理、任务队列、定时器,bottomhalf队列、系统调用、进程通信等部分组成。进程管理是Linux存储管理,文件管理,设备管理的基础。15进程控制块进程控制块是Linux系统最复杂的数据结构之一。Linux在内存空间中开辟了一个专门区域存放所有进程的进程控制块。系统初始化后,建立第一个task_struct数据结构INIT_TASK。新进程创建时,系统从内存分配新task_struct,占据1680个字节。16进程状态和标志进程标识进程控制块17进程的族亲关系进程控制块18进程间链接信息进程调度信息进程控制块19进程的时间信息进程的虚存信息进程控制块20进程的文件信息与进程间通信有关的信息进程控制块21其它信息进程控制块22进程状态定义了六种状态进程状态#defineTASK_RUNNING0#defineTASK_INTERRUPTIBLE1#defineTASK_UNINTERRUPTIBLE2#defineTASK_ZOMBIE4#defineTASK_STOPPED8#defineTASK_SWAPPING162324进程调度调度方法调度策略调度参数调度方法调度时机25调度方法Linux进程调度方式采用抢占调度方式(内核不抢占)进程分为普通进程和实时进程,分别采用不同的调度策略,实时进程的优先级高于普通进程。进程调度26调度策略进程调度27调度参数policy进程调度策略,可通过系统调用sys_sched_setscheduler()更改(kernel/sched.c)。•SCHED_OTHER非实时进程,基于优先级的轮转法•SCHED_FIFO实时进程,用先进先出算法•SCHED_RR实时进程,用基于优先权的轮转法进程调度28priority•进程优先级(静态),给出进程每次获取cpu后可使用的时间(按jitty计算)。通过系统调用sys_setpriority()改变。•Linux的基准时间(kernel/timer.c)。系统初始化时清零,以后每隔10ms由时钟中断服务程序,do_timer增1。进程调度29rt_priority实时进程的优先级,可通过系统调用sys_sched_setscheduler()改变.Counter•进程动态优先级表示进程当前还可运行多久•进程开始运行时被赋为priority值,以后,每隔一个tick(时钟中断)递减1,减到0时引起新一轮调度。•重新调度将从run-queue队列中选出counter值最大的就绪进程获得cpu。进程调度30进程调度调度方法采用动态优先级法,调度对象是可运行队列。进程在运行中,counter代表动态优先级。Linux采取了加权的方法来保证实时进程优先于普通进程。普通进程的权值就是它的counter的值,实时进程的权值是它的rt_priority的值加1000。调度过程中,调度程序检查可运行队列中所有进程的权值,选择其中权值最大的进程做为下一个运行进程。31staticinlineintgoodness(structtask_struct*p,structtask_struct*prev,intthis_cpu){intweight;if(p-policy!=SCHED_OTHER)return1000+p-rt_priority;weight=p-counter;……returnweight;}进程调度32调度时机时机1:进程状态发生变化时•处于运行态下的进程要等待某种资源•运行态下的进程在程序执行完毕后,通过调用内核函数do_exit()终止运行并转入僵死态。•处于等待态的进程被唤醒后,将加入到可运行队列中时•进程从运行态转入暂停态时•进程从暂停态成为可运行态时进程调度33时机2当前进程时间片用完时时机3进程从系统调用返回到用户态时时机4中断处理后,进程返回到用户态时。进程调度34进程控制进程创建过程进程状态间转换35进程创建过程为新进程分配任务结构体内存空间把父进程任务结构体拷贝到子进程任务结构体为新进程在其虚拟内存建立内核堆栈对子进程任务结构体中部分进行初始化设置把父进程有关信息拷贝给子进程,建立共享关系把子进程的counter设为父进程counter值的一半把子进程加入到可运行队列中结束do_fork()函数返回PID值进程控制36创建过程具体描述系统启动时创建第一个进程(0号进程)此时,系统只有这一个进程:初始化进程,运行在核心态初始化结束时,初始进程启动一个核心进程:init进程,也称为1号进程,然后执行空闲循环。系统空闲时,调度程序运行这个空闲进程。这个空闲进程的task_struct是唯一一个不是动态分配而是在核心连接时静态定义的,为了不至于混淆,叫做init_task。进程控制37进程由do_fork()函数创建intdo_fork(unsignedlongclone_flags,unsignedlongusp,structpt_regs*regs){为新进程申请PCB空间;if(申请不到)返回错误,退出;为新进程申请核心堆栈;if(核心堆栈申请不到)返回错误,退出;为新进程在Task向量表中找到空闲位置;/*复制父进程currentPCB中的信息,继承资源*/;p=current;进程控制38/*为防止信号、定时中断误唤醒未创建完毕的进程,将子进程的状态设成不可中断的*/p-state=TASK_UNINTERRUPTIBLE;/*跟踪状态和超级用户特权是没有继承性的,因为在root用户为普通用户创建进程时,出于安全考虑这个普通用户的进程不允许拥有超级用户特权。*/p-flags&=~(PF_PTRACED|PF_TRACESYS|PF_SUPERPRIV);/*将进程标志设成初建,但暂时不能运行,在进程第一次获得CPU时,内核将根据此标志进行一定操作*/p-flags|=PF_FORKNOEXEC;进程控制39开始Task_struct的初始化工作,如初始化进程时钟、信号、时间等数据;继承父进程所有资源:拷贝父进程当前打开的文件;拷贝父进程在VFS的位置;拷贝父进程的信号量;拷贝父进程运行的内存;拷贝父进程的线程;初始化工作结束,父进程将其将其唤醒,挂入running队列中,返回子进程的pid;进程控制4041进程状态间转换42转换说明sleep_on():TASK_RUNNING-TASK_UNINTERRUPTIBLE•拥有CPU的进程申请资源无效时,通过sleep_on(),将进程从TASK_RUNNING切换到TASK_UNINTERRUPTIBLE状态。•sleep_on()函数作用就是将current进程的状态置成TASK_UNINTERRUPTIBLE,并加到等待队列中。•一般来说引起状态变成TASK_UNINTERRUPTIBLE的资源申请,都是对一些硬件资源的申请,如果得不到这些资源,进程将不能执行下去,不能由signal信号或时钟中断唤醒回到TASK_RUNNING状态。进程状态间转换43interruptible_sleep_on():TASK_RUNNING-TASK_INTERRUPTIBLE•拥有CPU的进程申请资源无效时,通过该函数将进程从TASK_RUNNING切换到TASK_INTERRUPTIBLE状态。•interruptible_sleep_on()函数作用就是将current进程的状态置成TASK_INTERRUPTIBLE,并加到等待队列中。•处于TASK_INTERRUPTIBLE状态的进程可在资源有效时被wake_up()、wake_up_interruptible()或wake_up_process()唤醒,或收到signal信号以及时间中断后被唤醒。进程状态间转换44sleep_on_timeout():TASK_RUNNING-TASK_UNINTERRUPTIBLEinterruptible_sleep_on_timeout():TASK_RUNNING-TASK_INTERRUPTIBLE•虽然在申请资源或运行中出现了某种错误,但是系统仍然给进程一次重新运行的机会。调用该函数将进程从TASK_RUNNING切换到TASK_INTERRUTIBLE状态,并等待规定的时间片长度,再重新试一次。进程状态间转换45wake_up()TASK_UNINTERRUPTIBLE-TASK_RUNNINGTASK_INTERRUPTIBLE-TASK_RUNNING•处于TASK_UNINTERRUPTIBLE状态的进程不能由signal信号或时钟中断唤