第三章 Unix/Linux进程管理学习笔记
学习笔记
20191318 王泽文
《Unix/Linux系统编程》
第三章 Unix/Linux进程管理
本章讨论了Unix/Linux中的进程管理;阐述了多任务处理原则;介绍了进程概念;然后, 解释了Unix/Linux中各进程的来源;接着,对进程的执行模式进行了讲解,以及如何通过中断、异常和系统调用从用户模式转换到内核模式;再接着,描述了用于进程管理的Unix/Linux系统调用。
多任务处理
在计算机技术中,多任务处理指的是同时执行几个独立的任务。在单处理器(单CPU)系统中,一次只能执行一个任务。多任务处理是通过在不同任务之间多路复用CPU的执行时间来实现的,即将CPU执行操作从一个任务切换到另一个任务。不同任务之间的执行切换机制称为上下文切换,将—个任务的执行环境更改为另一个任务的执行环境。如果切换速度足够快就会给人一种同时执行所有任务的错觉。这种逻辑并行忡称为 “并发”。在有多个CPU或处理器内核的多处理器系统中,可在不同CPU上实时、 并行执行多项任务。
进程
进程是对映像的执行。
操作系统内核将一系列执行视为使用系统资源的单一实体。系统资源包括内存空间、I/O设备以及最重要的CPU时间。在操作系统内核中,每个进程用一个独特的数据结构表示,叫作进程控制块(PCB)或任务控制块(TCB)等。在本书中,我们直接称它为PROC结构体。与包含某个人所有信息的个人记录一样,PROC结构体包含某个进程的所有信息。 在实际操作系统中,PROC结构体可能包含许多字段,而且数抵可能很庞大。在PROC结构体中,next是指向下一个PROC结构体的指针,用于在各种动态数据结构(如链表和队列)中维护PROC结构体。ksp字段是保存的堆栈指针。当某进程放弃使用 CPU时,它会将执行上下文保存在堆栈中,并将堆栈指针保存在PROC.ksp中,以便以后恢复。在PROC结构体的其他字段中,pid是标识一个进程的进程ID编号,ppid是父进程ID 编号,status是进程的当前状态,priority是进程调度优先级,kstack是进程执行时的堆栈。
进程同步
一个操作系统包含许多并发进程,这些进程可以彼此交互。进程同步是指控制和协调进程交互以确保其正确执行所需的各项规则和机制。最简单的进程同步工具是休眠和唤醒操作。
睡眠模式
当某进程需要某些当前没有的东西时, 例如申请独占一个存储区域、 等待用户通过标准输人来输入字符等, 它就会在某个事件值上进入休眠状态, 该事件值表示休眠的原因。 为实现休眠操作, 我们可在 PROC 结构体中添加一个 event 字段, 并实现 ksleep(int event) 函数,使进程进人休眠状态。
唤醒操作
一个进程可能会进入休眠状态等待同一个事件,这是很自然的,因为这些进程可能都需要同一个资源,例如一台当前正处于繁忙状态的打印机。在这种情况下,所有这些进程都将休眠等待同一个事件值。当某个等待时间发生时,另一个执行实体(可能是某个进程或中断 处理程序)将会调用 kwakeup(event), 唤醒正处千休眠状态等待该事件值的所有程序。如果没有任何程序休眠等待该程序,kwakeup() 就不工作,即不执行任何操作。
进程终止
在操作系统中,进程可能终止或死亡,这是进程终止的通俗说法。
- 正常终止:进程调用 exit(value), 发出_exit(value) 系统调用来执行在操作系统内核中的 kexit(value)
- 异常终止:进程因某个信号而异常终止。
Unix/Linux中的进程
进程的执行模式
在 Unix/Linux 中, 进程以两种不同的模式执行, 即内核模式和用户模式, 简称 Kmode 和 Umode。
- 中断:中断是外部设备发送给 CPU 的信号,请求 CPU 服务 c 当在 Urnode 下执行时, CPU 中断是启用的因此它将响应任何中断。 在中断发生时, CPU 将进人 Kmode 来处 理中断, 这将导致进程进人 Kmode。
- 陷阱:陷阱是错误条件. 例如有效地址、 非法指令 、 除以0等, 这些错误条件被 CPU 识别为异常, 使得 CPU 进入 Kmode 来处理错误。 在 Unix/Linux 中, 内核陷阱处理程序将陷阱原因转换为信号编号, 并将信号传递给进程。 对于大多数信号 . 进程的默认操作是终止。
- 系统调用: 系统调用(简称 syscall) 是一种允许 Umode 进程进人 Kmode 以执行 内核函数的机制。
管道
管道是用千进程交换数据的单向进程间通信通道。管道有一个读取端和一个写入端。 可
从管道的读取端读取写人管道写入端的数据。
其他
编程实践
多任务处理系统
type.h文件定义了系统常数和表示进程的简单PROC结构体
ts.s文件
queue.c文件
t.c文件
运行结果
在64位的乌班图系统中,无法直接使用gcc -m32 t.c ts.s
指令进行32位的编译,使用
sudo apt-get install gcc-multilib
指令安装编译库后可进行32位编译。
当使用s q参数时会陷入死循环,根据循环判断是tswitch()
的问题,由于该函数为ts.s文件中设置,暂时无法解决。
fork()
函数
进程的执行顺序
等待和退出系统调用
Linux中的subreaoer
进程
通过ececl()
更改进程映像
b.c
a.c
通过execve()
更改进程映像
管道操作演示
命名管道操作