linux内核设计与实现学习笔记
进程管理
进程
Fork()
父进程 子进程
Exec() 载入程序
Exit():进程退出执行,处于僵死状态
负责进程内存销毁(task_struct保留)
Wait4()::子进程退出执行或子进程在
Ptrace下中断而出发wait4
负责查看子进程的task_struct并
销毁它,销毁后子进程彻底消失
Fork(),vfork(),__clone() -> clone() -> do_fork() -> copy_process() ->dup_task_struce()
1.Dup_task_struct() 为新进程创建一个内核线程,thread_info,和task_struct,新建的结构值和父进程完全一样。
2.检查新进程创建后,用户拥有的进程数是否超出给他分配的资源限制
3.进程描述符的大多成员被赋值为初始值(这是父进程与子进程区别开来),进程描述符的大多数数据都是共享的(比如进程打开的文件描述符)
4.子进程的状态被设置为TASK_UNINTERRUPTIBLE
5.copy_process()调用copy_flags()设置进程的一些标志位
6.调用get_pid()为进程获取一个PID
7.根据传递给clone()的参数标志,copy_process()拷贝或共享打开的文件,文件系统信息,信号处理函数,进程地址空间和命名空间等
进程的退出do_exit()
1、将task_struce中的标志成员设置为PF_EXITING
2、调用del_timer_syne()删除任一内核定时器(挂起)
3、调用_exit_mm()放弃进程占用的mm_struct,(mm_struct的共享计数-1,如果为0则彻底释放他)
4、调用exit_sem()退出进程通信,如果进程排队等候IPC,它离开队列
5、调用_exit_files()递减文件描述符
6、调用_exit_fs()文件系统数据
7、调用exit_namespace()进程名字空间
8、调用exit_sighand()信号处理函数的引用计数
9、将task_struct中的exit_code码标示为exit()提供的参数
10、调用exit_notify()向父进程发出信号,将本身的状态设置为TASK_ZOMBIE
11、调用schedule()切换到其他进程
注:处于ZOMBIE状态的进程不会再被调用,他占用的资源仅为内核站、thread_info,task_struct.
进程描述符的终结
父进程调用wiat(),他的基本动作是挂起调用他的进程,直到其中的一个子进程退出,此时函数会返回该子进程的PID。
wait4会调用release_task()调用一下函数完成进程描述符的释放工作:
1、调用free_uid来减少进程拥有者的进程计数
2、调用unhash_process()从pidhash上删除该进程,同时也要从task_list中删除该进程
3、如果进程正在被ptrace跟踪,release_task()将跟踪的附近横重设为其最初的父进程并将其在ptrace_list中删除
4、调用put_task_struct()释放进程内核栈和thread_info结构所占用的页,释放task_struct所占用的slab高速缓存
程序的执行:将可执行文件载入到进程的地址空间执行,一帮的命令是在用户空间执行,在程序调用了系统调用或触发了异常则会陷入内核空间。
Linux下进程和线程的区别:
Linux没有具体划分进程和线程,处理器执行的基本单位是进程,而所谓的“进程的多个线程”是指共享地址空间但是有独自的进程描述符的进程组