Linux内核设计与实现第六周读书笔记
第三章 进程管理
3.1 进程
进程是处于执行期的代码。通常进程还要包含其他资源,像打开的文件、挂起的信号、内核的内部数据、处理器状态、一个或多个具有内存映射的内存地址空间及一个或多个执行线程,当然还包括用来存放全局变量的数据段等。
进程提供两种虚拟机制:虚拟处理器和虚拟内存。
通常,创建新的进程都是为了立即执行新的、不同的程序,而接着调用exec()这组函数就可以创建新的地址空间,并把新的程序载入其中。
3.2 进程描述符以及任务结构
内核把进程的列表存放在叫做任务队列(task list)的双向链表中。链表中的每一个项都是类型为task_struct(processdescriptor
进程描述符)的结构。该结构定义在<linux/sched.h>
中。
进程描述符中包含的数据能完整地描述一个正在执行的程序:它打开的文件、进程的地址空间、挂起的信号、进程的状态,还有其他更多信息。
3.2.1分配进程描述符
Linux通过slab分配器分配task_struct
结构,各个进程的task_struct
存放在它们内核栈的尾端,这样做是为了让那些像x86那样寄存器较少的硬件体系结构只要通过栈指针就能计算出它的位置。
struct thread_info
在文件<asm/thread_info.h>
中定义:
struct thread_info {
struct task_struct *task;
struct exec_domain *exec_domain;
unsigned int flags;
unsigned int status;
unsigned int cpu;
int preempt_count;
mm_segment_t addr_limit;
struct restart_block restart_block;
void *sysenter_return;
int uaccess_err;
};
3.2.2进程描述符的存放
内核通过一个唯一的进程标识值(process identification value
)或PID来标识每个进程。PID是一个数,表示为pid_t隐含类型,实际上就是一个int类型。PID的最大值默认设置为32768,这受<linux/threads.h>
中所定义PID最大值的限制。如果确实需要的话,可以不考虑与老式系统的兼容,由系统管理员通过修改/proc/sys/kernel/pid_max
来提高上限。
3.2.3进程状态
进程描述符中的state域描述了进程的当前状态,该域的值也必为下列五种状态之一:
- TASK_RUNNING(运行)—进程是可执行的。
- TASK_INTERRUPTIBLE(可中断)—进程正在睡眠,等待某些条件的达成。
- TASK_UNINTERRUPTIBLE(不可中断)
- TASK_TRACED—被其他进程跟踪的进程。
- TASK_STOP(停止)—进程停止执行。
3.2.4设置当前进程状态
内核经常需要调整某个进程的状态,这时最好使用set_task_state(task,state
)函数。参看<linux/sched.h>
中对这些相关函数实现的说明。
3.2.5进程上下文
一般程序在用户空间执行。当一个程序执行了系统调用或者触发了某个异常,它就陷入了内核空间。此时,我们称内核“代表进程执行”并处于进程上下文中。
3.2.6进程家族树
Unix系统的进程之间存在一个明显的继承关系,所有的进程都是PID为1的init进程的后代。内核在系统启动的最后阶段启动Init进程。该进程读取系统初始化脚本(initscript
)并执行其他的相关程序,最终完成系统启动的整个过程。
每个task_struct
都包含一个指向其父进程task_struct
、叫做parent的指针,还包含一个称为children的子进程链表。
获得父进程的进程描述符:Struct task_struct *my_parent = current->parent
访问子进程:
Struct task_struct *task;
Struct list_head *list;
List_for_each(list, ¤t->children){
Task = list_entry(list,struct task_struct, sibling);
/*task指向当前某个子进程*/
}
获取下一个进程和前一个进程:
Task = list_entry(task->tasks.next, struct task_struct, tasks);
Task = list_entry(task->tasks.perv, struct task_struct, tasks);
3.3 进程创建
分解到两个单独的函数中去执行:fork()和exec()。
- 首先,fork()通过拷贝当前进程创建一个子进程,子进程与父进程的区别仅仅在于PID、PPID和某些资源和统计量。
- exec() 函数负责读取可执行文件并将其载入地址空间开始运行。
3.3.1写时拷贝
Linux的fork()使用写时拷贝(copy-on-write
)页实现。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候才进行。
3.3.2fork()
Linux中通过clone()系统调用实现fork()。Fork()、vfork()、和__clone()
库函数根据各自需要的参数标志去调用clone(),然后由clone()去调用do_fork()
。
do_fork完成了创建中的大部分工作。该函数调用copy_process()
,然后让进程开始运行。
3.3.3vfork()
vfork()
的好处就仅限于不拷贝父进程的页表项。
3.4线程在linux中的实现
Linux把所有的线程都当做进程来实现。线程仅仅被视为一个与其它进程共享某些资源的进程。每个线程都拥有惟一隶属于自己的task_struct
。
3.4.1创建线程
线程的创建和普通进程的创建类似,只不过在调用clone()的时候需要传递一些参数标志来指明需要共享的资源:clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SINHAND , 0)
;
普通的fork()的实现:clone(SIGCHILD, 0)
;
vfok()的实现:clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)
;
clone使用的参数标志定义在<linux/sched.h>
中。
3.4.2内核线程
内核线程和普通的进程间的区别在于内核线程没有独立的地址空间。
内核线程也只能由其他内核线程创建。内核是通过从kthreadd内核进程中衍生出所有新的内核线程来自动处理这一点的。在<linux/kthread.h>
中申明有接口,从现有内核线程中创建一个新的内核线程的方法:
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data,
const char namefmt[],
...)
新的任务是由kthread内核进程通过clone()系统调用而创建的。穿件一个进程并让它运行起来,可以通过调用kthread_run()
来达到:
struct task_struct *kthread_run(int (*threadfn)(void *data),
void *data,
const char namefmt[],
...)
内核线程启动后就一直运行直到调用do_exit()
退出,或者内核的其他部分调用kthread_stop()
退出。
3.5 进程终结
一般来说,进程的析构是自身引起的。它发生在进程调用exit()系统调用时,既可能显式地调用这个系统调用,也可能隐式地从某个程序的主函数返回。不管进程是怎么终结的,该任务大部分都要靠do_exit()
来完成。
至此,与进程相关联的所有资源都被释放掉了。进程不可运行并处于EXIT_ZOMBIE
退出状态。它占用的所有内存主要就是内核栈、thread_info
和task_struct
结构。此时进程存在的唯一目的就是向它的父进程提供信息。父进程检索到信息后,或者通知内核那是无关的信息后,由进程所持有的剩余内存被释放,归还给系统调用。
3.5.2孤儿进程造成的进退维谷
对于孤儿进程的解决办法:
解决办法就是给子进程在当前线程组内找到一个线程作为父亲,如果不行,就让init做它们的父进程。
在do_exit()
中会调用exit_notify()
,该函数会调用forget_original_parent()
,而后者会调用find_new_reaper()
来执行寻父过程。
Linux内核设计与实现第六周读书笔记的更多相关文章
- LINUX内核设计与实现第三周读书笔记
LINUX内核设计与实现第三周读书笔记 第一章 LINUX内核简介 1.1 Unix的历史 1969年的夏天,贝尔实验室的程序员们在一台PDR-7型机上实现了Unix这个全新的操作系统. 1973年, ...
- Linux内核设计与实现第十周读书笔记
第十七章 设备与模块 关于设备驱动与设备管理,我们讨论四种内核成分. 设备类型 模块 内核对象 sysfs 17.1设备类型 在Linux以及所有Unix系统中,设备被分为以下三种类型: 块设备,块设 ...
- Linux内核设计与实现第八周读书笔记
第四章 进程调度 进程在操作系统看来是程序的运行态表现形式. 4.1多任务 多任务操作系统就是能同时并发地交互执行多个进程的操作系统. 多任务操作系统会使多个进程处于堵塞或者睡眠状态.这些任务尽管位于 ...
- Linux内核设计与实现第五周读书笔记
第十八章 调试 18.1准备开始 需要的只是: 一个确定的bug.大部分bug通常都不是行为可靠而且定义明确的. 一个藏匿bug的内核版本. 相关的内核代码的知识和运气. 18.2内核中的bug 内核 ...
- linux内核设计与实现第七周读书笔记
第七章 链接 链接(linking)是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储并执行.链接可以执行于编译时(compile time),也就是在源代 ...
- 《Linux内核设计与实现》Chapter 5 读书笔记
<Linux内核设计与实现>Chapter 5 读书笔记 在现代操作系统中,内核提供了用户进程与内核进行交互的一组接口,这些接口的作用是: 使应用程序受限地访问硬件设备 提供创建新进程与已 ...
- 《Linux内核设计与实现》Chapter 18 读书笔记
<Linux内核设计与实现>Chapter 18 读书笔记 一.准备开始 一个bug 一个藏匿bug的内核版本 知道这个bug最早出现在哪个内核版本中. 相关内核代码的知识和运气 想要成功 ...
- 《Linux内核设计与实现》Chapter 3 读书笔记
<Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...
- 《Linux内核设计与实现》第四周读书笔记——第五章
<Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...
随机推荐
- 进阶篇:4.1)DFA设计指南:简化产品设计(kiss原则)
本章目的:理解kiss原则,明确如何简化产品的设计. 1.前言:kiss原则,优化产品的第一原则 如果要作者选出一个优化产品的最好方法,那一定是kiss原则莫属.从产品的整体设计到公差的分析,kiss ...
- selenium 各种很奇葩的异常
问题1:使用selenium3+java的脚本模拟登陆时,总是提示用户名,密码错误 解决方法:1 在执行输入用户名和密码的代码之前,加上driver.navigate().refresh(); QQ群 ...
- windows环境下apache-apollo服务器搭建及发布订阅测试
查证了一些资料之后,发现 apache-apollo服务器使用的人还是挺多的,资料也比较齐全,所以直接选择 apache-apollo了,具体性能如何,先用起来再说吧: 1.下载 apache-apo ...
- MySQL5.6.14从安装到启动全过程
1.下载 地址:http://dev.mysql.com/downloads/mysql/ 这里选择的是Linux-Generic平台,下载了MySQL-5.6.14-1.linux_glibc2.5 ...
- leetcode-每个节点的右向指针(填充同一层的兄弟节点)
给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } 填充它的每个 ...
- Kubernetes v1.10----部署kubernetes-dashboard v1.83
Kubernetes v1.10----部署kubernetes-dashboard v1.83 1.下载 kubernetes-dashboard yaml文件 #因为文件中的image指定的是谷 ...
- 75.[LeetCode] Sort Colors
Given an array with n objects colored red, white or blue, sort them in-place so that objects of the ...
- Halcon算子解释
Halcon算子解释大全 Halcon/Visionpro视频教程和资料,请访问 重码网,网址: http://www.211code.com Chapter 1 :Classification 1. ...
- win7重装系统后设置Python2.7环境
起因 台式机的主板莫名出现问题,显示器画面卡顿不能动,鼠标键盘无反应,在这种情况下只好按住电源键断电.下面重启后,显示器无画面,猜测开机后没有进BIOS.然后就拆机箱,拔下电源线后撬起主板电池几秒再放 ...
- Yogurt factory
Description The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. Over the ...