本文共 2002 字,大约阅读时间需要 6 分钟。
第3章 进程管理
1 进程(process):处于执行期的程序和相关资源的总称
相关资源: – 打开的文件 – 挂起的信号 – 内核内部数据 – 处理器状态 – 一个或多个具有内存映射的内存地址空间 – 一格或者多个执行线程 – 存放全局变量的数据段2 线程(thread):在进程中活动的对象,拥有独立的:
– 程序计数器 – 进程栈 – 一组进程寄存器3 内核调度的对象是thread而不是process
4 在现代操作系统中,进程提供两种虚拟机制:
– 虚拟处理器 – 虚拟内存5 同一个进程中的线程可以共享虚拟内存,但拥有各自的虚拟处理器
6 fork()系统调用从内核返回两次:
– 一次回到父进程 – 一次回到新产生的子进程7 进程的另一个名字是task
8 内核把进程的列表存放在叫做任务列表(task list)的双向循环链表中,链表中的每一项都是类型为task_struct、称为进程描述符(process description)的结构
/* task_struct定义 */
9 linux通过 slab分配器 分配 task_struct 结构
10 在x86上, struct thread_info定义如下:
struct thread_info { struct task_struct *task; __u32 flags; __u32 status; __u32 cpu; mm_segment_t addr_limit; unsigned int seg_on_uaccess_error:1; unsigned int uaccess:1;};
11 内核通过一个唯一的进程标识值PID(proccess identification value)来标识每一个进程
12 系统中允许存在的进程的最大数目(受“linux/threads.h”中所定义PID的最大值的限制),可以通过更改 /proc/sys/kernel/pid_max来实现
13 进程描述符中的state域描述了进程的当前状态
14 设置当前进程状态
#include
set_task_state(task, state);
15 进程上下文:当一个程序执行了系统调用后者触发某个异常,它就陷入了内核空间。此时,我们称内核“代表进程执行”并处于进程上下文中
16 内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本(initscript)并执行其他的相关程序,最终完成系统启动的整个过程
17 进程间的关系被放在进程描述符中
18 对于当前进程,可以通过如下方式获取父进程的进程描述符:
struct task_struct *my_parent = current->parent;
19 依次访问子进程:
struct task_struct *task;struct list_head *list;list_for_each(list, ¤t->children){ /* task现在指向当前的某个子进程 */ task = list_entry(list, struct task_struct, sibling);}
20 对于给定的进程,获取链表中的前/下一个进程:
list_entry (task->tasks.prev, struct task_struct, tasks)list_entry (task->tasks.next, struct task_struct, tasks)
21 进程创建
①fork()通过拷贝当前进程创建一个子进程 ②exec()读取可执行文件并将其载入地址空间开始执行22 任务队列是一个双向的循环链表
23 copy-on-write是一种可以推迟甚至免除拷贝数据的技术。资源复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享
24 fork()的实际开销:
①复制父进程的页表 ②给子进程创建唯一的进程描述符17 linux通过clone()系统调用实现fork()
– fork->clone->do_fork->copy_proccess: – ->dup_task_struct – ->copy_flags – ->alloc_pid18 在现有内核线程中创建新的内核线程
struct task_struct *kthread_create (int (*threadfn)(void *data), void *data, const char namefmf[], ...)
转载地址:http://sfvsi.baihongyu.com/