一切为了进程
进程是处于执行期的程序以及相关的资源的总称
进程的虚拟机制
- 虚拟处理器
进程觉得自己在独享处理器 - 虚拟内存
进程觉得自己在独享内存
线程之间可以共享虚拟内存,但每个都拥有各自的虚拟处理器
其实在linux中,线程和进程的区别不大,只是一种进程间共享资源的手段而已。线程和进程的创建都是调用clone实现的,只不过传入的参数不同而已。
进程生命周期相关的函数
fork() 他爹生他出来
复制一个现有的进程来创建一个全新的进程
exec() 他自己成家立业
为fork()的新进程读取可执行文件并将其载入地址空间开始运行
exit() 他死了
退出进程的执行并释放其占用的资源
wait() 他爹给它收尸
为什么unix要把创建一个进程拆分成fork和exec两部分?
我认为是为了进程的快速执行(我自己的理解)
利用写时拷贝技术。
当子进程的页根本不需要被写入的时候,无需复制
当子进程立马这些exec的时候,也无需复制
这样子进程就可以快速的执行啦
进程描述符
我认为,在linux中,任何一个“概念”都会有其对应的描述符
进程的描述符为struct task_struct,它能够完整的描述一个进程:进程打开的文件,进程的地址空间,挂起的信号,进程的状态等。
- 系统中所有的进程描述符都存放在一个叫做任务队列(task_list)双向循环链表中。遍历整个任务队列:for_each_process(struct task_struct *task)
- linux通过slab分配器分配task_struct,这样能达到对象复用和缓存着色的目的。(什么是缓存着色?)
- 每个任务的 task_struct存放在它的内核栈的尾端(内核栈其他地方放的哪些?顺序是什么?) 通过current宏可以查找当前正在运行的进程的 task_struct
进程描述符的各个域
unsigned long state;//进程的当前状态(五种状态之一);
pid_t pid; //进程标识值,所有的进程都是pid为1的init进程的后代;
进程家族树:
children
parent
进程创建
fork() --> clone() -->do_fork() -->copy_process()
其中,clone()是系统调用
copy_process()函数的工作:
- 为新进程创建内核栈,thread_info和task_struct
- 修改一些必须和父进程不一样的属性
- 分配PID
- 根据clone传入的参数拷贝和共享一些东西比如进程地址空间等
进程终结
当一个进程死了(调用exit())之后要释放它占有的所有资源并且把这个消息告诉他的父进程,同时还要给他的儿子们找养父(从他所在的线程组中去找,找不到合适的话就托给init),最后等他爹来给他收尸埋掉(调用wait())才算完。
进程死了,只是他所占用的资源释放放了,但是他的进程描述符还在。这样做是为了让系统有办法在进程死了之后还能获得进程的信息,当系统确定了确实用不上之后,他的进程描述符才被释放掉
内核线程
内核线程是独立运行在内核空间的标准进程,与普通进程的区别在于它没有独立的地址空间(指向地址空间的mm指针被设置为NULL)。他们只在内核空间运行,不在用户空间运行。
注意内核线程创建不是用fork(),当然不能用fork啦,因为fork是库函数,内核不可以用库函数!
内核线程是由其他内核线程调用一下函数创建的,
kthread_create() //这个函数还是调用的clone()
kthread_run()
kthread_stop()
3304

被折叠的 条评论
为什么被折叠?



