进程管理(1)
进程
进程是处于执行期的程序,进程包括代码段,数据段,还有PCB(进程控制块)
线程实在进程中活动的对象,内核调度的对象是线程,而不是进程
注意:Linux内核通常把进程叫做任务
进程描述符及任务结构
内核把进程的列表存放在任务队列中(双向循环链表)
链表中的每一项类型都是task_struct(称为进程描述符),进程描述符包含一个具体进程的所有信息
分配进程描述符
看书说实话我还没怎么看懂
进程描述符的存放
内核是通过唯一的进程标识符或PID来标识每个进程
PID是一个数,标识位pid_t隐含类型,实际上就是一个int类型(PID最大值默认为32768)
进程状态
进程描述符中的state描述了进程的当前状态
五种状态我先略过了(第二遍再仔细看)
设置当前进程状态
通过set_task_state(task,state)函数
进程上下文
进程只有通过系统调用和异常处理程序接口才能陷入内核执行
对内核的所有访问必须通过这些接口
进程家族树
在Linux系统中,所有的进程都是PID为1的init进程的后代
内核在系统启动的最后阶段启动init进程,该进程读取系统的初始化脚本并执行其他的相关程序,最终完成系统启动的整个过程
系统的每个进程必定有一个父进程,每个进程可以拥有零个或多个子进程
拥有同一个父进程的所有进程被称为兄弟
每个task_struct都包含一个指向其父进程task_struct,叫做parent的指针
还包含一个称为children的子进程链表
进程创建
其他操作系统都提供产生进程的机制,首先在新的地址空间里创建进程,读入可执行文件,最后开始执行
Unix则采用了与众不同的实现方式,将两个步骤分解到两个单独的函数执行
fork() 函数通过拷贝当前进程创建一个子进程
子进程和父进程的区别
1.PID
2.PPID(父进程的进程号)
3.某些资源和统计量
exec() 函数负责读取可执行文件并将其载入地址空间开始运行
写时拷贝
传统的fork()系统调用直接把所有的资源复制给新创建的进程
Linux的fork()使用写时拷贝
内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝
只有在需要写入时,数据才会被复制,从而使各个进程拥有各自的拷贝
fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描