第三章 进程管理

一、多任务处理

多任务处理指的时同时进行几项独立活动的能力。多任务处理是通过在不同任务之间多路复用CPU执行时间来实现的。如果切换速度够快,就会给人一种通知执行所有任务的错觉。这种逻辑并行性称为“并发”。

二、进程

在操作系统中,任务也成为进程。进程是对映像的执行。

操作系统内核将一系列执行视为使用系统资源的单一实体。系统资源包括内存空间、I/O设备以及最重要的CPU时间。PROC结构体包含了某个进程的所有信息。

学习笔记6_子进程

三、多任务处理系统

多任务处理系统,简称MT,由以下几个部分组成

1、type.h文件

type.h文件定义了系统常熟和表示进程的简单PROC结构体
学习笔记6_linux_02

学习笔记6_linux_03

2、ts.s文件

ts.s在32位GCC汇编代码中可实现进程上下文切换。

学习笔记6_子进程_04

3、queue.c文件

queue.c文件可实现队列和链表操作函数。enqueue()函数按优先级将PROC输入队列中。在优先级队列中,具有相同优先级的进程按照FIFO的顺序排序。dequeue()函数可返回从队列或链表中删除的第一个元素。printList()函数可打印链表元素。

学习笔记6_父进程_05

4、t.c文件

t.c文件定义MT系统数据结构、系统初始化代码和进程管理函数

学习笔记6_多任务处理_06

学习笔记6_系统调用_07

学习笔记6_子进程_08

学习笔记6_linux_09

学习笔记6_系统调用_10

学习笔记6_多任务处理_11

四、进程同步

一个操作系统包含许多并发进程,这些进程可以彼此交互。进程同步是指控制和协调进程交互以确保其正确执行所需要的各项规则和机制。最简单的进程同步工具是休眠和唤醒操作。

1、休眠模式

为实现休眠操作,我们可在PROC结构体中添加一个event字段,并实现ksleep(int event)函数,使进入休眠状态。接下来,我们将假设对PROC结构体进行修改以包含加粗显示的添加字段

学习笔记6_父进程_12

学习笔记6_父进程_13

2、唤醒操作

当某个等待时间发生时,另一个执行实体将会调用kwakeup(event),唤醒正处于休眠状态等待该事件值的所有程序。如果没有任何程序休眠等待该程序,kwakeup()就不工作。kwakeup()算法:
学习笔记6_多任务处理_14

五、进程终止

  • 正常终止:进程调用exit(value),发出_exit(value)系统调用来执行在操作系统内核中的kexit(value)。

  • 异常终止:进程因某个信号而异常终止。

1、kexit()的算法

在所有类Unix系统中,进程P1(又叫INIT进程)将所有其他的孤儿进程,不论死亡还是活跃都被送到P1中,称为P1的子进程。

2、进程家族树

学习笔记6_多任务处理_15

3、等待子进程终止

在任何时候,进程都可以调用内核函数

pid = kwait(int *status)

在kwait算法中,如果没有子进程,则进程会返回-1,表示错误。否则,他将搜索僵尸子进程。如果他找到僵尸子进程,就会收集僵尸子进程的pid和退出代码。相应的,当进程终止时,他必须发出:

kwakeup(running->parent)

唤醒父进程。

六、Unix/Linux中的进程

1、进程来源

强行创建PID=0初始进程—>系统执行初始进程P0—>挂载一个跟文件系统—>P0复刻出一个子进程P1

2、INIT和守护进程

3、登陆进程

4、sh进程

当用户成功登录时,LOGIN进程会获取用户的gid和uid,从而称为用户的进程。他将目录更改为用户的主目录并执行列出的程序,通常是命令解释程序sh。

5、进程的执行模式

在Unix/Linux中进程以两种不同的模式执行,即内核模式和用户模式

学习笔记6_linux_16

一旦进入Umode就不能随意更改CPU的状态。

七、进程管理的系统调用

1、fork()

int pid = fork()

fork()创建子进程并返回子进程的pid。

2、进程终止

(1)正常终止:当内核中的某个进程终止时,他会将_exit(value)系统调用中的值记录为进程PROC结构体中的退出状态。并通知他的二父进程并使该进程成为僵尸进程。父进程课通过系统调用找到僵尸子进程,获得其pid和退出状态

pid=wait(int *status)

(2)异常终止:当某进程遇到异常时,他会陷入操作系统内核。内核的异常处理程序将陷阱错位类型转换为一个幻数,称为信号,将信号传递给进程,时进程终止。用户可以使用命令

kill -s signal_numeber pid

向通过pid识别的目标发送信号。

3、等待子进程终止

在任何时候,一个进程都可以使用

int pid = wait(int *status);

系统调用,等待僵尸子进程。

4、环境变量

各环境变量定义为:

关键字=字符串

重要环境变量:

SHELL=/bin/bash
TERM=xterm
USER=kcw
PATH=/usr/1oca1/bin:/usr/bin:/bin:/usr/local/games:/usr/games:./
HOME= / home /kcw

SHELL:指定将解释任何用户命令的sh。

TERM:指定运行sh时要模拟的终端类型。

USER:当前登录用户。
PATH:系统在查找命令时将检查的目录列表。
HOME:用户的主目录。在 Linux 中,所有用户主目录都在/home中。

在sh会话中,可以将环境变量设置为新的(字符串)值,如:

HOME= / home / newhome

可通过EXPORT命令传递给后代sh,如

expoert HOME

八、I/O重定向

sh进程有三个用于终端IO的文件流: stdin(标准输入)、stdout(标准输出)和stderr(标准错误)。每个流都是指向执行映像堆区中FILE结构体的一个指针,如下文所示。
学习笔记6_多任务处理_17

九、管道

管道时用于进程交换数据的单向进程件通信通道。管道有一个读取端和一个写入端。

1、管道命令处理

在Unix/Linux中,命令行

cmd1 | cmd2

sh将通过一个进程运行cmd1,并通过另一个进程运行cmd2,他们通过一个管道连接在一起,因此cmd1的输出变为cmd2的输入

2、命令管道

命令管道又叫FIFO

(1)在sh中,通过mknod命令创建一个命令管道:

mknod mypipe p

(2)或在c语言中发出mknod()系统调用

int r = mknod("mypipe",s_IFIFP,0);

(3)进程可像访问普通文件一样发个文命名管道。

编程练习

1、fork()演示

学习笔记6_父进程_18
学习笔记6_linux_19
第一行打印正在执行进程的PID和新复刻子进程的PID。
第二行打印子进程的PID,以及其父进程的PID。

2、进程执行顺序

学习笔记6_linux_20
学习笔记6_父进程_21
学习笔记6_多任务处理_22

3、等待进程终止

学习笔记6_linux_23
学习笔记6_linux_24

4、env

学习笔记6_linux_25

5、ulimit()

学习笔记6_父进程_26
学习笔记6_系统调用_27

6、码云链接

https://gitee.com/lhp6666/linux/tree/master/