Linux操作系统分析 Chapter9进程管理 陈香兰(xlanchend@ustc.edu.cn) 计算机应用教研室。计算机学院 嵌入式系统实验室苏州研究院 中国科学技术大学 Fa112014 December 23,2014 1口t4四1是142月00 陈香兰(xlanchenouste,edu,cn)(升异款应Lnux棕作系统分行Chapter 9注任管理 December 23.2014 1 /95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Linux操作系统分析 Chapter 9 进程管理 陈香兰(xlanchen@ustc.edu.cn) 计算机应用教研室@计算机学院 嵌入式系统实验室@苏州研究院 中国科学技术大学 Fall 2014 December 23, 2014 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 1 / 95
Outline ○进程描逑符 。Linux的进程描遂符:task_struct ●进程的栈和thread info数据结构 。进程相关的几个链表 ●proC文件系统简介 进程的等待和唤醒 ③进程切换 ●进程上下文 ●上下文切换 进程的创建和删除 。进程的创建 ●Linux的进程创建 。内核线程及其创建 ●进程树及其开始 ·进程的终止和刷除 ○进程调度 ·进程的分类 ●Linux中的调度策略和调度算法 ●Linux-2.6.26中的调度相关数据结构和代码 ●Linux2.6.26中的优先级及其设置 需小结和作业 1口4四1是4P在刀00 练查兰(xlanchenoustc,.ed加,cn)(升界丸应Linuxs操作系统分折Chapter 0连花管现 December 23.2014 2/95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Outline . 1. 进程描述符 Linux的进程描述符:task_struct 进程的栈和thread_info数据结构 进程相关的几个链表 proc文件系统简介 .2 进程的等待和唤醒 .3 进程切换 进程上下文 上下文切换 4. 进程的创建和删除 进程的创建 Linux的进程创建 内核线程及其创建 进程树及其开始 进程的终止和删除 5. 进程调度 进程的分类 Linux中的调度策略和调度算法 Linux-2.6.26中的调度相关数据结构和代码 Linux2.6.26中的优先级及其设置 .6 小结和作业 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 2 / 95
进程和线程 。多道程序,对操作系统的需求→进程 。进一步提高并发度,对操作系统的需求→线程 ·进程是执行程序的一个实例 ·几个进程可以并发的执行一个程序 ·一个进程可以顺序的执行几个程序 。进程和程序的区别?线程和进程的区别? ●Linux2.4内核以及之前的版本都不支持线程 Linux2.6内核中有thread,但仍不是线程 ~Linux中的线程主要在用户态实现,不是本课程的内容 ~但Liux内核对用户态线程有一定的辅助支持 4口4四1是14P,刀00 东香兰(xlanchenoustc,ed加,cn)(计异丸应L1nux操作系统分折Chapter 0注在管理 December 23.2014 4 /95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 进程和线程 . . 多道程序,对操作系统的需求⇒进程 进一步提高并发度,对操作系统的需求⇒线程 进程是执行程序的一个实例 ▶ 几个进程可以并发的执行一个程序 ▶ 一个进程可以顺序的执行几个程序 进程和程序的区别?线程和进程的区别? Linux 2.4内核以及之前的版本都不支持线程 Linux 2.6内核中有thread,但仍不是线程 ▶ Linux中的线程主要在用户态实现,不是本课程的内容 ▶ 但Linux内核对用户态线程有一定的辅助支持 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 4 / 95
唯一的标识一个进程 ●使用进程描述符地址 ·进程和进程描述符之间有非常严格的一一对应关系,使得 用32位进程描述符地址标识进程非常方便 O使用PID(Process ID,PID) ~每个进程的PID都存放在进程描述符的pid域中 常用接口getpid() 在/proc文件系统中列出所有的进程 1s /proc -U 1口4四1是42在月0C 陈香兰(xlanchenoustc,ed加,cn)(计异款应Linux操作系统分折Chapter 9洗任管理。 December 23.2014 5/95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 唯一的标识一个进程 1. 使用进程描述符地址 ▶ 进程和进程描述符之间有非常严格的一一对应关系,使得 用32位进程描述符地址标识进程非常方便 2. 使用PID (Process ID,PID) ▶ 每个进程的PID都存放在进程描述符的pid域中 ▶ 常用接口getpid() . 在/proc文件系统中列出所有的进程 . . ls /proc -U 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 5 / 95
Outline ①○进程描逑符 ●Linux的进程描速符:task_struct 。进程的钱和thread info最据结物 。进程相关的几个佳表 。proc文件系航简价 进程的等待和唤醒 进程切提 。进程上下文 a上下文切换 ●进程的创建和则除 。进程的创建 o Linux的进程创建 。内核线程及其创建 。进程树及其开焰 。近程的终止和刷 进程调度 。进程的分美 aLix中的调度菜略和调度算法 o Linux-2.6.26中的调度相关数据结构和代码 0L山x2.6.26中的优先级及其设盟 小结和作 4口4四1是14P,刀00 东奇兰(x1 anchenoustc,ed加,cn)(计异款应Linux操作系统分折Chapter 9注任管理 December 23.2014 6 95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Outline . 1. 进程描述符 Linux的进程描述符:task_struct 进程的栈和thread_info数据结构 进程相关的几个链表 proc文件系统简介 .2 进程的等待和唤醒 .3 进程切换 进程上下文 上下文切换 4. 进程的创建和删除 进程的创建 Linux的进程创建 内核线程及其创建 进程树及其开始 进程的终止和删除 5. 进程调度 进程的分类 Linux中的调度策略和调度算法 Linux-2.6.26中的调度相关数据结构和代码 Linux2.6.26中的优先级及其设置 .6 小结和作业 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 6 / 95
Linux的进程描述符:task struct ·为了管理进程,内核必须对每个进程进行清晰的描述。 ·进程描述符提供了内核所需了解的进程信息· struct task struct(参见源文件:include/1inux/sched.h) ·数据结构很庞大 ★基本信息 ★管理信息 ★控制信息 示意图,参见ULK 。进程描述符的分配/回收,参见kernel/fork.c #ifndef HAVE_ARCH_TASK_STRUCT_ALLOCATOR define alloc_task_struct()kmem_cache_alloc(task_struct_cachep,GFP_KERNEL) define free_task_struct(tsk)kmem_cache_free(task_struct_cachep,(tsk)) static struct kmem_cache task_struct_cachep: #endif 4口4四是4P在刀0C 陈香兰(xlancherouste,edu,cn)(升界丸应Linuxs操作系统分行Chapter 9过在管理 ecember23.20147/95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Linux的进程描述符:task_struct 为了管理进程,内核必须对每个进程进行清晰的描述。 进程描述符提供了内核所需了解的进程信息。 struct task_struct(参见源文件:include/linux/sched.h) ▶ 数据结构很庞大 ⋆ 基本信息 ⋆ 管理信息 ⋆ 控制信息 ▶ 示意图,参见ULK 进程描述符的分配/回收,参见kernel/fork.c . . #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR # define alloc_task_struct() kmem_cache_alloc(task_struct_cachep, GFP_KERNEL) # define free_task_struct(tsk) kmem_cache_free(task_struct_cachep, (tsk)) static struct kmem_cache *task_struct_cachep; #endif 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 7 / 95
Linux进程的状态:task struct::state volatile long state;/-1 unrunnable,0 runnable,>0 stopped include/1inux/sched.h /Task state bitmask.NOTE!These bits are also encoded in fs/proc/array.c:get_task_state(). We have two separate sets of flags:task->state is about runnability,while task->exit_state are about the task exiting.Confusing,but this way modifying one set can't modify the other one by ◆mistake, #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 state是按bit定义的 #define TASK_UNINTERRUPTIBLE 2 除TASK_RUNNING,其他都是状态位掩码 #define_TASK_STOPPED #define TASK_TRACED 当不处于其他任何状态时,即TASK RUNNING 8 in tsk->exit_state ' Linux:还定义了一些宏 #define EXIT_ZOMBIE 16 (1)一些组合状态 #define EXIT_DEAD 32 (2)关于状态的判断 /in tsk->state again (3)关于状态的设置 #define TASK_DEAD 64 #define TASK_WAKEKILL 128 东香兰(xlanchenoustc,edu.cn) (计算机应 Lu操作系分所Chapter D程管现 December 23.2014 8/95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Linux进程的状态:task_struct::state volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ . include/linux/sched.h . . /* * Task state bitmask. NOTE! These bits are also * encoded in fs/proc/array.c: get_task_state(). * * We have two separate sets of flags: task->state * is about runnability, while task->exit_state are * about the task exiting. Confusing, but this way * modifying one set can’t modify the other one by * mistake. */ #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 /* in tsk->exit_state */ #define EXIT_ZOMBIE 16 #define EXIT_DEAD 32 /* in tsk->state again */ #define TASK_DEAD 64 #define TASK_WAKEKILL 128 state是按bit定义的 除TASK_RUNNING, 其他都是状态位掩码 当不处于其他任何状态时,即TASK_RUNNING Linux还定义了一些宏 (1)一些组合状态 (2)关于状态的判断 (3)关于状态的设置 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 8 / 95
Linux进程的pid及其分配 o task struct中: pid_t pid; pid_t tgid; ●类型定义 include/linux/types.h: typedef kernel_pid_t pid_t: include/asm-arm/posix_types.h:typedef int kernel_pid_t: ●pid的取值范围[O,PID MAX DEFAULT) include/linux/threads.h: #define PID_MAX_DEFAULT (CONFIG_BASE_SMALL 0x1000 0x8000) 。进程创建过程中,使用al1 oc_pid分配进程的pid do_fork-→copy_process--→alloc_pid ●pid位图和pid名字空间,参见include/1inux/pid namespace.h 1口4四是42刀00 东香兰(x1 anchenoustc,ed加,cn)(计异款应Linux操作系统分行Chapter 9注任管理 December 23.2014 9/95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Linux进程的pid及其分配 task_struct中: pid_t pid; pid_t tgid; 类型定义 include/linux/types.h: typedef __kernel_pid_t pid_t; include/asm-arm/posix_types.h:typedef int __kernel_pid_t; pid的取值范围[0,PID_MAX_DEFAULT) include/linux/threads.h: #define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000) 进程创建过程中,使用alloc_pid分配进程的pid ▶ do_fork−→copy_process−→alloc_pid pid位图和pid名字空间,参见include/linux/pid_namespace.h 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 9 / 95
用户如何获得一个进程的pid o getpid,getppid -get process identification (注意:返回tgid) kernel/timer.c / sys_getpid -return the thread group id of the current process Note,despite the name,this returns the tgid not the pid.The tgid and the pid are identical unless CLONE_THREAD was specified on clone()in which case the tgid is the same in all threads of the same group. *This is SMP safe as current->tgid does not change. asmlinkage long sys_getpid(void)( return task_tgid_vnr(current); / asmlinkage long sys_getppid(void){ pid task_tgid_vnr(current->real_parent); +。+ 东香兰(xlanchenoustc,ed.cm)(计异丸应 L1nux操作系统分标Chapter 0注在管理 Decenber 23.2014 10/95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 用户如何获得一个进程的pid getpid, getppid - get process identification (注意:返回tgid) . kernel/timer.c . . /** * sys_getpid - return the thread group id of the current process * * Note, despite the name, this returns the tgid not the pid. The tgid and * the pid are identical unless CLONE_THREAD was specified on clone() in * which case the tgid is the same in all threads of the same group. * * This is SMP safe as current->tgid does not change. */ asmlinkage long sys_getpid(void) { return task_tgid_vnr(current); }/ ... asmlinkage long sys_getppid(void) { ... pid = task_tgid_vnr(current->real_parent); ... } 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 10 / 95
逻辑CPU的当前进程:current宏 ●Current.宏可以看成当前进程的进程描述符指针, 在内核中直接使用 include/asm-arm/current.h static inline struct task_struct 'get_current(void)attribute_const_; static inline struct task_struct 'get_current(void) return current_thread_info()->task: #define current (get_current()) ,举例:比如current->pid返回在CPU上正在执行的进程的PID ,观察内核中对current的使用情况 ,问题:current.所代表的进程什么时候被切换? 4口4四1是14P刀00 陈香兰(x1 anchenoustc,edu,cn)(计界机应Lnux操作系统分折Chapter 9注狂管理 Decenber23,201411/95
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 逻辑CPU的当前进程:current宏 Current宏可以看成当前进程的进程描述符指针, 在内核中直接使用 . include/asm-arm/current.h . . static inline struct task_struct *get_current(void) __attribute_const__; static inline struct task_struct *get_current(void) { return current_thread_info()->task; } #define current (get_current()) ▶ 举例: 比如current->pid返回在CPU上正在执行的进程的PID ▶ 观察内核中对current的使用情况 ▶ 问题:current所代表的进程什么时候被切换? 陈香兰(xlanchen@ustc.edu.cn) (计算机应用教研室 Linux操作系统分析Chapter 9 进程管理 @计算机学院嵌入式系统实验室@苏州研究院中国科学技术大学Fall 2014) December 23, 2014 11 / 95