Linux内核设计与实现第三章读书笔记

178 阅读1分钟

进程的概念

进程就是正在执行中的的程序和其所使用资源的总称。

进程的特性

所有进程都是初始init进程的后代,进程之间是树的结构关系。

进程线程的关系

在Linux内核中进程线程都使用进程描述符即并不严格区分二者,只是将线程视为某进程的子进程。

Linux如何存放和表示进程

内核通过名为进程描述符的结构表示进程,其结构类型是task_struct。通过进程描述符组成名为task list任务队列的双向循环链表。

每个task_struct在32位机器上大约占1.7KB内存。

 // linux/sched.h
 struct task_struct{
     unsigned long state;
     int prio;
     unsigned long policy;
     struct task_struct *parent;
     struct list_head tasks;
     pid_t pid;
     // ...
 }

分配task_struct结构

内核通过slab分配器动态分配task_struct,在每个内核栈的栈底创建一个thread_info结构体,其中的task存放指向实际指向task_struct的指针。

 // asm/thread_info.h
 struct thread_info{
     struct task_struct *task;
     // ...
 }

创建进程

  • spawn == fork + exec族

写时拷贝

注意copy on write(写时拷贝)的优化思路:创建进程先使父子进程共享地址空间,只有到子进程需要写入时再拷贝。

fork()

graph LR
fork/vfork/__clone-- 调用 ---> clone函数 -- 调用 ---> do_fork -- 实现 ---> fork的功能 

vfork的缺陷(答书P28页的设想)

如果exec()调用失败,会导致死锁。

如何把新的执行映像装入地址空间*

exec()系统调用族

如何表示进程的层次关系*

想想树形结构

父进程如何收集后代的信息*

wait()系统调用

进程的消亡

调用exit()进程自己体面或帮进程体面

孤儿进程

父进程在该子进程之前终止,init进程会成为子进程新的父进程,init进程会清理掉僵尸进程。