Linux进程管理与调度.ppt_第1页
Linux进程管理与调度.ppt_第2页
Linux进程管理与调度.ppt_第3页
Linux进程管理与调度.ppt_第4页
Linux进程管理与调度.ppt_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux进程管理与调度,关于进程与线程 Linux进程实现 Linux进程调度策略 Linux进程调度实现,1 Linux进程与线程,Linux进程 Linux线程,进程作为资源分配的基本单位而存在,线程作为调度的基本单位而存在 我们都知道linux是不断发展的.在早期版本中, linux的基本调度单元是Task, 只到现在, 依然是它. 在早期版本中, 一个Task对应着一个进程, 完全没有线程这个概念. 随着时间的发展, 线程的概念出现的, 但是linux并没有马上接受这一概念, 要知道, 线程是现代操作系统的特征, 向一个现有的操作系统内核引入线程是一件伤筋动骨的事情, 更何况在线程概

2、念的早期, 受历史原因(UNIX)和硬件的限制(多核尚不是主流), 线程的地位尚不确定. 所以, linux并没有在内核中引入线程的概念. 但是, linux提供了一个新的系统调用clone, 通过该系统调用, 内核中的多个进程可以共享一些信息, 比如进程空间等. 注意, 此时linux内核的基础调度单元依然是Task, 而且在内核看来, 一个进程依然对应着一个Task,2 Linux进程实现,Linux进程描述符也称 进程控制块PCB: shruct task_struct unsigned long state; /进程的状态,在2.6.23已经有9个状态 unsigned long po

3、licy; /描述进程调度策略.判断是实时进程还是非实时进程 struct task_struct *parent; /组织进程的层次关系,指向父进程 struct list_head tasks; /通过list_head组织成双向链表 pid_t pid; /每个进程唯一的标号 . ;,Linux进程描述符,在内核栈底创建新的结构struct thread_info Struct thread_info struct task_struct *task; struct exec_domain *exec_domain; unsigned long flags; unsigned long

4、status; _u32 cpu; ; 在linux内核中,进程被分为两部分,一部分是thread_info,保存在内核栈中,为了保持很小,因此只保存了必须的几个域,它有一个变量task,指向task_struct,这个结构保存了进程相关的所有信息。而对应的task_struct也保存了一个变量stack指向的就是一个thread_union的联合体,Linux进程实现相关的系统调用,fork(): 创建普通进程,copy on write(要复制父进程的页表) 创建后子进程和父进程指向同一内存区域,仅当子进程有write发生时候,才会把改动的区域copy到子进程新的地址空间 vfork():

5、 共享创建,完全无拷贝。(子进程作为父进程的一个单独线程在其地址空间运行,父进程阻塞) clone(): 介于fork()和vfork()之间,可以指定共享什么,拷贝什么。 说明:vfork()与clone()可用于创建新的内核线程,Linux进程实现相关的函数,do_fork():/ 被clone(),fork(),vfork()调用,执行步骤如下: 检查父进程标志是否为空。 调用alloc_task_struct()为新进程分配一段内存空间,并将父进程描述符的内容拷贝到子进程。 检查进程是否得到所需资源及系统当前允许的最大进程数。 如进程需要引用内核模块,则增加模块引用计数。 更新从父进程

6、拷贝来的信息。 系统调用get_pid(),将获得的pid赋给新建的子进程。 更新不能由父进程继承的域,为新进程的执行设置跟踪进程的相关内核数据结构,新进程入链表。 置新进程状态为task_running, 。 向父进程返回pid。 说明: 创建进程的系统调用返回时(ret_from_sys_call),将根据存放系统调用返回值寄存器EAX的内容(pid)是0还是一个小正整数来决定是运行父进程还是子进程。 在linux中第一个进程是内核进程,pid为0,它是所有的进程的父进程。这个进程也叫swapper,或者说是idle,Linux进程状态,TASK_RUNNING:进程在运行 ( 是系统的当

7、前进程 ) 或者准备运行(等待被安排到系统的一个CPU上)。 TASK_INTERRUPTIBLE:进程处于某个等待队列中,它能够被信号(signal)唤醒。等待资源的请求满足时,也被唤醒。 TASK_UNINTERRUPTIBLE:进程处于某个等待队列中,不能被信号或中断唤醒,只有等待的资源被满足时才被唤醒。 TASK_ZOMBIE: 进程已经停止,但还没有释放进程控制块。 TASK_STOPPED:可能是被特定的信号终止,也可能是受其它进程的跟踪调用而暂时将CPU交给跟踪它的进程,Linux状态转换,scheduler and dispatcher,线程的实现 在Linux系统中,线程被当

8、作与其他进程共享某些资源的进程. 线程的创建:与普通进程相似,需要指明共享资源。 如:clone (CLONE_VM | CLONE_FS | CLONE_FILES|CLONE_SIGHAND,0); 对比:clone (SIGCHLD, 0) /普通的fork() clone (CLONE_VFORK | CLONE_VM | SIGCHLD, 0) 内核线程:内核进程没有独立的地址空间,只在内核空间运行。通常是一些后台执行的任务。 通过clone()的参数,新创建的进程,也称为LWP(Lightweight process)与父进程共享内存空间,文件句柄,信号处理等,从而达到创建线程相同

9、的目的,5 Linux进程调度策略,1) 抢占式调度策略 当一个进程进入TASK_RUNNING状态,内核检查其优先级是否高于当前进程。 当一个进程的时间片为0时,也会被抢占。 抢占: 用户抢占:need_resched标志设置即发生,包括从系统调用返回用户空间、 从中断处理程序返回用户空间的情况。 内核抢占:为每个进程的thread_info引入了preempt_count计数器,该计数 器初值为0,加锁时,其值加1,其数值为0时,内核可执行抢 占。中断返回内核空间时产生,Linux进程调度策略,2) 时间片调度策略 内核根据时间片是否耗尽为标准,将就绪进程分为active, expired

10、两类。 新创建的子进程和父进程均分父进程的剩余时间片 时间片的计算以静态优先级为基础,即由task_timeslice()函数根据静态优先级按照比例缩放。 时间片的递减和重置在时钟中断中进行,sheduler_tick() 时间片计算: MIN_TIMESLICE+(MAX_TIMESLICE MIN_TIMESLICE)*(MAX_PRIO-1-(p)-static_prio)/(MAX_USER_PRIO-1) 即:将100139的优先级映射到200ms10ms的时间片上,5 Linux进程调度策略,3) 优先级调度策略 基于动态优先级的调度策略 进程优先级取值范围:0.139,动态优先级

11、prio根据静态优先级static_prio变化,由effective_prio()函数取得,该函数根据进程实际的睡眠平均时间分级成-50+5奖罚优先级值范围。 用户赋予优先级nice转换为静态优先级:static_prio=120+nice 动态优先级设置时机: 1)进程创建时 2)唤醒休眠进程时,会修正进程的优先级 3)在时钟中断中的schedule_tick()中 4)其他:IDLE进程初始化、负载平衡、修改nice值、修改调度策略,effective_prio()函数: 计算非实时进程的优先级,主要步骤如下: 算出当前进程平均睡眠时间。 得到进程的动态优先级。 static int e

12、ffective_prio(task_t *p) if (rt_task(p) return p- prio; bonus = CURRENT_BONUS(p) MAX_BONUS / 2; prio = p-static_prio bonus; return prio; 说明:系统通过一系列宏计算出bonus. bonus = (进程睡眠jiffers/HZ )*10 - 5,effective_prio()函数: 计算非实时进程的优先级,主要步骤如下: 算出当前进程平均睡眠时间。 得到进程的动态优先级。 static int effective_prio(task_t *p) if (rt

13、_task(p) return p- prio; bonus = CURRENT_BONUS(p) MAX_BONUS / 2; prio = p-static_prio bonus; return prio; 说明:系统通过一系列宏计算出bonus. bonus = (进程睡眠jiffers/HZ )*10 - 5,6 Linux进程调度实现,可执行队列 基本数据结构:runqueue 定义在kernel/sched.c中 struct runqueue spinlock_t lock; /运行队列自旋锁 unsigned long ru_running; /任务数目 struct prio

14、_array *active; /活动优先级队列 struct prio_array *expired; /超时优先级队列 struct prio_array arrays2; /实际优先级数组,Linux进程调度实现,优先级数组 struct prio_array int nr_active; /任务数目 unsigned long bitmapBITMAP_SIZE;/优先级位图 struct list_head queueMAX_PRIO;/优先级队列 说明:每个运行队列有2个优先级数组,一个活跃的,一个过期的。能够 提供 O(1)级算法复杂度的数据结构,Linux进程调度实现,优先级数

15、组的重置 通过维护2个优先级数组,active,expired, active数组上的进程还有剩余时间片,expired数组上的进程全部耗尽了时间片。 当一个进程时间片到了会从active数组移到expired数组,而时间片事先计算好了,这里的重新计算时间片只需在两个数组之间切换即可,调度的实现,每个进程的进程描述符中与进程调度相关的域如下: volatile long need_resched; 确定是否需要重新调度的标志。 unsigned long policy; 确定调度策略 SCHED_FIFO /先进先出的实时调度 SCHED_RR /基于优先级的循环轮转实时调度 SCHED_NO

16、RMAL /普通分时调度,rt_priority;实时进程的优先级(099) nice:用户可控制的进程优先级因子。(-2019) prio : 进程的动态优先级 static_prio: 进程的静态优先级 sleep_avg: 进程的平均睡眠时间 static_prio = MAX_RT_PRIO + nice + 20,schedule()函数 功能:选择一个合适的进程运行。 主要步骤 清理当前运行进程 选择下一个运行的进程 设置新进程的运行环境 执行进程上下文切换 后期整理,直接启动调度: 发生在当前进程因等待资源而需要进入被阻塞状态时。 把当前进程放到适当的等待队列中 把当前进程的state设为TASK_INTERRUPTIBEL或者TASK_UNINTERRUPTIBEL; 调用schedule(), 准备让新的进程使用CPU; 检查当前进程所需的资源是否可用,如果是,把当前进程从等待队列里删除,否则回到

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论