linux内核源代码分析-进程管理及调度.ppt
《linux内核源代码分析-进程管理及调度.ppt》由会员分享,可在线阅读,更多相关《linux内核源代码分析-进程管理及调度.ppt(43页珍藏版)》请在三一办公上搜索。
1、进程管理、调度,进程管理任务进程管理与其他模块的依赖关系进程描述符及任务队列进程的创建(FORK,copy-on-write)线程实现进程的终止进程调度,进程管理的任务,允许进程复制自己(真正作到一个应用多进程)确定哪个进程能够拥有CPU接受中断并将中断导向相应的内核子系统向用户进程发送信号管理时钟硬件 当一个进程结束时,释放其资源动态装载执行模块,进程模块与其他模块的依赖关系在整个内核中的功能位置和源码依赖关系,进程模块与其他模块的依赖关系进程调度模块的内外界面,对用户进程提供了一组简单的系统调用接口;对内核的其他模块提供了丰富的接口功能。,进程模块与其他模块的依赖关系进程调度模块和其他模块
2、的相互依赖关系,内存管理模块:当一个进程被调度的时候,为它建立内存映射。IPC子模块:bottom-half处理使用了其中的信号量队列。文件系统模块:在装载module的时候为进程调度提供实际设备的 访问途径。所有的其他模块都依赖于进程调度模块,因为当要进行硬件访问的时候它们需要CPU挂起用户进程,切换到系统态进行处理。,.,进程描述符及任务队列,分配进程描述符(http:/)预分配描述符(SLAB机制),把动态分配的过程省略掉一部分(不需要频繁调用内存管理响应功能),相当于一种高级缓存,提高效率。最后的操作主要是直接填写结构。,进程描述符的存放PID(为兼容原来的PID为unsigned s
3、hort,最大32767,可以通过/proc修改设置)获得当前进程描述符的指针(CURRENT宏、专门寄存器),进程描述符及任务队列,进程状态#define TASK_RUNNING 0(进程是可执行的或正在执行)#define TASK_INTERRUPTIBLE 1(进程睡眠或阻塞,等待某一事件到来中断它)#define TASK_UNINTERRUPTIBLE 2(进程睡眠或阻塞,不能其他进程的信号打断,直接等待硬件条件)#define TASK_ZOMBIE 4(僵尸,呆傻状态,已结束,但其父进程未接到通知,描述符未释放)#define TASK_STOPPED 8(进程停止,接受到S
4、IGSTP信号)#define TASK_SWAPPING 16(进程页面被兑换出内存),进程描述符及任务队列,进程状态转换图(见书17页)设置当前进程状态(有很多情况会设置进程状态(思考)set_task_state(task,state))进程的上下文(进程环境:用户、资源等)系统调用时,内核“代表进程”执行,上下文有效进程之间的联系也属进程的环境(INIT为第一个进程,描述符中Parent,Children指针将这种环境连接起来,可以从任一个进程出发遍历系统的所有进程),进程描述符及任务队列,索引组织形式之一:队列,进程描述符及任务队列,索引组织形式之二:树,进程的创建(FORK,cop
5、y-on-write),进程创建过程描述Linux中,进程的创建是通过拷贝已存在进程来实现的。在Linux内核启动的时候,首先由start_kernel()初始化各个系统数据结构,同时生成了和系统共存亡的后台进程:init。init进程通过拷贝自身,产生了若干内核子进程。然后这些进程就可以通过系统调用fork()生成它们的子进程,当然这些子进程的原始数据都是他们的父亲的副本。进程的终止是通过系统调用_exit()实现的。,LINUX中的进程创建FORK():进程复制自身产生其子进程EXEC():加载可执行代码模块覆盖自身代码COPY_ON_WRITE:写时copy,进程的创建(FORK,cop
6、y-on-write),FORK()FORK()、VFORK()、_CLONE()=CLONE()=DO_FORK()(在kernel/fork.c中)=COPY_PROCESS(),并执行dup_task_struct(建内核栈、thread_info、task_struct);检查进程数目限制;描述符设置,以区别于父进程;子进程状态设置为TASK_UNINTERRUPTIBLE copy_flags get_pid 资源引用复制 父子进程平分剩余时间片 返回指向子进程的指针(一般子进程先执行)(注意:此时并未复制代码),进程的创建(FORK,copy-on-write),EXEC()对应内
7、核中一族函数:execve(),execv(),execlp(),execvp()负责加载可执行的代码,覆盖本进程的代码、数据。,COPY_ON_WRITE:写时copyLINUX的FORK()过程并未为新生成的进程马上复制代码,开始的进程仅仅读共享父进程代码。直到进程第一次要对进程空间有写请求时,再复制代码。这样做的好处:效率高(一般新进程要有自己的代码,第一条就是EXEC()),进程的创建(FORK,copy-on-write),FORK()应用实例main()pid_tpid;pintf(“this location in parent processn”);if(pid=fork()=
8、0)printf(“this location in child processn”);execlv(.);,进程的创建(FORK,copy-on-write),VFORK()除不拷贝父进程的页表项和FORK()完全相同。目前已基本不用。体会一下书上20页有关VFORK()主要过程的描述,线程实现,Linux没有真正的线程(线程与进程的比较)仅仅是进程之间资源直接共享的一种机制通过CLONE时参数实现:请看一下书21页的有关描述(有些参数标明共享打开文件)。相当于实现了线程概念的一部分(资源共享)。内核线程独立运行在内核的标准进程(后面章节再做讨论),进程的终止,进程运行结束时要释放相应的资源
9、,通过EXIT()调用实现(显式或隐式)EXIT()实现时调用了do_exit()完成以下工作Task_struct中标志成员设为:PF_EXITING调用_exit_mm()调用sem_exit()调用_exit_files(),_exit_fs(),exit_name_space,exit_sighand退出代码替换为EXIT()提供的代码调用Exit_notify()向父进程发信号,(标为ZOOMBIE)调用shedule切换到其他进程,进程的终止,删除进程描述符父进程得知子进程终止的消息后才能删除子进程的描述符。(思考:若父进程异常终止,将会发生什么情况)父进程WAIT(),返回时可以
10、根据代码做相应动作(或者IGNORE),动作完成后真正释放描述符(调用release_task)调用free_uid:进程记数Unhash_process():删除pidhash中的项同时删除task_list中的项若有trace删除ptrace_list对应项调用put_task_struct释放描述符,(内核栈、threadinfo所占的页、slab高速缓存。,进程调度,抢占式(preemtive)和非抢占式(cooprative)进程调度的策略IO消耗型和CPU消耗型进程UNIX系列的倾向于IO消耗型优先进程的优先级动态优先级(调度程序根据情况增或减其优先数-20-19)时间片长短定义是
11、个很矛盾的事情(默认一个值)LINUX提供可变长的时间片进程抢占LINUX用抢占式调度(一个新的进程进入时,要看优先级别)调度策略的活动(一个编辑程序和一个后台程序比较),进程调度,调度算法-LINUX调度在2.5以后的实现目标O(1)调度 SMP的可扩展性强化SMP的亲和力(尽量将相关的一组任务分配给一个CPU)加强交互性保证公平对多CPU的支持增强(忙时每个CPU都有进程执行)主要问题:怎样实现了O(1)调度?,进程调度,LINUX围绕以下几个方面对调度算法进行改进运行队列在 2.4 内核中,就绪进程队列是一个全局数据结构,调度器对它的所有操作都会因全局自旋锁而导致系统各个处理机之间的等待
12、,使得就绪队列成为一个明显的瓶颈。在 2.6 中,就绪队列定义为一个复杂得多的数据结构 struct runqueue,并且,尤为关键的是,每一个 CPU 都将维护一个自己的就绪队列,-这将大大减小竞争。1)prio_array_t*active,*expired,arrays2 每个 CPU 的就绪队列按时间片是否用完分为两部分,分别通过 active 指针和 expired 指针访问,active 指向时间片没用完、当前可被调度的就绪进程,expired 指向时间片已用完的就绪进程。每一类就绪进程都用一个 struct prio_array 的结构表示:,进程调度,图中的 task 并不是
13、 task_struct 结构指针,而是 task_struct:run_list,这是一个小技巧,详见下面 run_list 的解释。2.4版本里选择最佳侯选进程是schedule()进行的(O(n)),在新的 O(1)调度中,这一查找过程分解为 n 步,每一步所耗费的时间都是 O(1)量级的。prio_array 中包含一个就绪队列数组,数组的索引是进程的优先级(共 140 级,详见下“static_prioqueue 中。调度时直接给出就绪队列 active 中具有最高优先级的链表中的第一项作为候选进程(参见”调度器“),而优先级的计算过程则分布到各个进程的执行过程中进行”属性的说明),
14、相同优先级的进程放置在相应数组元素的链表。为了加速寻找存在就绪进程的链表,2.6 核心又建立了一个位映射数组来对应每一个优先级链表,如果该优先级链表非空,则对应位为 1,否则为 0。核心还要求每个体系结构都构造一个 sched_find_first_bit()函数来执行这一搜索操作,快速定位第一个非空的就绪进程链表。采用这种将集中计算过程分散进行的算法,保证了调度器运行的时间上限,同时在内存中保留更加丰富的信息的做法也加速了候选进程的定位过程。这一变化简单而又高效,是 2.6 内核中的亮点之一。arrays 二元数组是两类就绪队列的容器,active 和 expired 分别指向其中一个。ac
15、tive 中的进程一旦用完了自己的时间片,就被转移到 expired 中,并设置好新的初始时间片;而当 active 为空时,则表示当前所有进程的时间片都消耗完了,此时,active 和 expired 进行一次对调,重新开始下一轮的时间片递减过程,进程调度,struct prio_array int nr_active;/*本进程组中的进程数*/struct list_head queueMAX_PRIO;/*以优先级为索引的 HASH 表,见下*/unsigned long bitmapBITMAP_SIZE;/*加速以上 HASH 表访问的位图,见下*/;,进程调度,2)spinlock
16、_t lock runqueue 的自旋锁,当需要对 runqueue 进行操作时,仍然应该锁定,但这个锁定操作只影响一个 CPU 上的就绪队列,因此,竞争发生的概率要小多了。3)task_t*curr本 CPU 正在运行的进程。4)tast_t*idle 指向本 CPU 的 idle 进程,相当于 2.4 中 init_tasksthis_cpu()的作用。5)int best_expired_prio 记录 expired 就绪进程组中的最高优先级(数值最小)。该变量在进程进入 expired 队列的时候保存。6)unsigned long expired_timestamp 当新一轮的时
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 内核 源代码 分析 进程 管理 调度
![提示](https://www.31ppt.com/images/bang_tan.gif)
链接地址:https://www.31ppt.com/p-5437933.html