第三章学习笔记
第三章 Unix/Linux进程管理
本章框架图
知识点概括
0、摘要
本章讨论了 Unix/Linux 中的进程管理;阐述了多任务处理原则;介绍了进程概念;以一个编程示例来说明多任务处理、上下文切换和进程处理的各种原则和方法。多任务处系统支持动态进程创建、进程终止,以及通过休眠与唤醒实现进程同步、进程关系,以及二叉树的形式实现进程家族树,从而允许父进程等待子进程终止;提供了一个具体示例来阐释进程管理函数在操作系统内核中是如何工作的;解释了 Unix/Linux 中各进程的来源,包括系统启动期间的初始进程、INIT 进程、守护进程、登录进程以及可供用户执行命令的 sh 进程;对进程的执行模式进行了讲解,以及如何通过中断、异常和系统调从用户模式转换到内核模式;描述了用于进程管理的 Unix/Linux 系统调用,包括 fork、wait、exec 和 exit ;阐明了父进程与子进程之间的关系,包括进程终止和父进程等待操作之间关系的详细描述;解释了如何通过 INIT 进程处理孤儿进程,包括当前 Linux 中的 subreaper 进程,并通过示例演示了 subreaper 进程;详细介绍了如何通过 exec 更改进程执行映像,包括 execve 系统调用、命令行参数和环境变量;解释了 I/0 重定向和管道的原则及方法,并通过示例展示了管道编程的方法。
1、多任务处理:同时执行几个独立的任务
通过在不同任务之间多路复用CPU的执行时间
(不同任务之间的切换机制称为【上下文切换】)
如果切换速度足够快,就会给人一种同时执行所有任务的错觉。这种逻辑并行性称为“并发”。
进程的正式定义:进程是对映像的执行。
在操作系统内核中,每一个进程用一个独特的数据结构表示
多任务处理系统,简称MT,由以下几个部分组成:
type.h文件
:定义系统常数和表示进程的简单PROC结构体
ts.s文件
:可实现进程上下文切换
queue.c文件
:可实现队列和链表操作函数
t.c文件
:定义MT系统数据结构、系统初始化代码和进程管理函数
2、多任务处理系统(MT)代码介绍
. (1)虚拟CPU
. (2)init();
. (3)P()调用kfork()来创建优先级为1 的子进程P1
. (4)tswitch()实现进程上下文切换
|| SAVE函数 || SAVE函数将CPU寄存器保存到调用任务的堆栈中,并将堆栈指针保存到proc.ksp中;
|| scheduler函数 || 在执行SAVE函数之后,任务调用scheduler来选择下一个正在运行的任务;
|| RESUME函数 || 将CPU的堆栈指针设置为当前运行任务的已保存堆栈指针
. (5)kfork() 创建一个子任务并将其输入readyQueue中
. (6)为便于演示,所有创建的任务都执行同一个body()函数
在body()执行时,进程提示输入char=[ f | s | q ]命令,其中:
f:kfork一个新的子进程来执行body()
s:切换进程
q:终止进程,并将进程以freeList中的FREE函数的形式返回
. (7)空闲任务P0
. (8)运行多任务处理(MT)系统:在Linux下,输入: gcc -m32 t.c s.s
MT系统的输出示例:
3、
(1)睡眠模式
为实现休眠操作,我们可以在 PROC结构体中添加一个event字段,并实现ksleep(int event)函数,使进程进入休眠状态。接下来,我们将假设对 PROC结构体进行修改以包含加粗显示的添加字段。
(2)唤醒操作
当某个等待时间发生时,另一个执行实体(可能是某个进程或中断处理程序)将会调用 kwakeup(event)。唤醒正处于休眠状态等待该事件值的所有程序。如果没有任何程序休眠等待该程序,kwakeup()就不工作,即不执行任何操作。
4、进程终止
● 正常终止:进程调用exit(value),发出 exit(value)系统调用来执行在操作系统内核中的 kexit(value),这就是我们本节要讨论的情况。
● 异常终止:进程因某个信号而异常终止。信号和信号处理将在后面第6章讨论。在这两种情况下,当进程终止时,最终都会在操作系统内核中调用kexit()。
进程家族树
等待子进程终止
在任何时候,进程都可以调用内核函数pid = kwait(int *status)
等待僵尸子进程。如果成功,则返回的pid是僵尸子进程的 pid
,而 status包含僵尸子进程的退出代码。此外,kwait()
还会将僵尸子进程释放回freeList
以便重用。
5、MT系统中的进程管理
完善基础MT系统,实现MT系统的进程管理函数:
. (1)用二叉树的形式实现进程家族树。
. (2)实现 ksleepO()和kwakeup()进程同步函数。
. (3)实现kexit()和kwait()进程管理函数。
. (4)添加"w"命令来测试和演示等待操作。
修改后的MT系统的输出示例
6、Unix/Linux中的进程
(1)守护进程
例如:
syslogd: log daemon process
inetd :Internet service daemon process
httpd : HTTP server daemon process
etc.
(2)进程的执行模式
1.中断:中断是外部设备发送给 CPU的信号,请求CPU服务。
2.陷阱:陷阱是错误条件,例如无效地址、非法指令、除以0等、这些错误条件被CPU识别为异常,使得CPU进入 Kmode 来处理错误。
3.系统调用:系统调用(简称syscall)是一种允许Umode 进程进入Kmode 以执行内核函数的机制。如果发生错误,外部全局变量 errno(在errno. h中)会包含一个ERROR代码,用于标识错误。用户可使用库函数
perror( "error message");
7、进程管理的系统调用
(1)fork()操作
(2)进程终止
1.正常终止:回顾前面的内容,我们知道,每个C程序的 main()函数都是由C启动代码 crt0.o调用的。如果程序执行成功,main()最终会返回到 crt0.o,调用库函数 exit((0)来终止进程。首先,exit(value)函数会执行一些清理工作,如刷新 stdout、关闭I/O流等。然后,它发出一个_exit(value)系统调用,使进入操作系统内核的进程终止。
2.异常终止:在执行某程序时,进程可能会遇到错误,如非法指令、越权、除零等,这些错误会被 CPU识别为异常。当某进程遇到异常时,它会进入操作系统内核。内核的异常处理程序将陷阱错误类型转换为一个函数,称为信号,将信号传递给进程,使进程终止。
8、I/0重定向
重定向标准输出
当进程执行库函数:printf("format=%s\n",items);
它试图将数据写入 stdout 文件FILE 结构体中的 fbuf[],这是缓冲行。如果 fbuf[]有一个完整的行,它会发出一个write系统调用,将数据从 fbuf[]写入文件描述符1,映射到终端屏幕上。要想将标准输出重定向到一个文件,需执行以下操作:
c1ose(1);
open("filename",O_WRONLY|O_CREAT,0644);
更改文件描述符1,指向打开的文件名。然后,stdout 的输出将会转到该文件而不是屏幕。同样,我们也可以将stderr重定向到一个文件。当某进程(在内核中)终止时,它会关闭所有打开的文件。
实践内容:
我们可以通过 ps 命令得到一个进程列表
ps [options] [--help]
常用选项
-A
,显示所有进程信息
**ps -ef [ | grep 进程关键字] **