第 15 章 进程控制

22
第 15 第 第第第第 Linux 第 第第第第第第第第 第第第第第第第第第第第第第第第第 第第第第第 ,。 统统 第第第第第第第 第第第第 第第第第 第第第第第第第第第第第第第第第第 第第第第第第 ,。 第第第第第第第第第第 第第第第第第第 第第第第 第第 第第第第第第第第第第 第第第 ,体 ,。 统统 第第第第第第第第第第第 第第第第第第 第第第第第第第第第第第 第第第第第第第第第第 第第第第第第第第第第

description

第 15 章 进程控制. Linux 系统是多任务操作系统,可同时进行多个程序完成多项工作。进程是处于活动状态的程序,在操作系统的管理下,所有进程共享计算机中的硬件资源。进程作为系统运行时的基本逻辑成员,不仅作为独立个体运行在系统上,而且还将相互竞争系统资源。了解进程的本质对于理解、描述和设计系统软件有着极为重要的意义,了解进程的活动状态也有利于设计复杂的程序。. 15.1 进程的基本概念. 在讨论进程的基本概念之前,我们首先介绍两种查看 Linux 系统中进程信息的方法。. 15.1.1 进程状态和状态转换. - PowerPoint PPT Presentation

Transcript of 第 15 章 进程控制

Page 1: 第 15 章  进程控制

第 15 章 进程控制

Linux 系统是多任务操作系统,可同时进行多个程序完成多项工作。进程是处于活动状态的程序,在操作系统的管理下,所有进程共享计算机中的硬件资源。进程作为系统运行时的基本逻辑成员,不仅作为独立个体运行在系统上,而且还将相互竞争系统资源。了解进程的本质对于理解、描述和设计系统软件有着极为重要的意义,了解进程的活动状态也有利于设计复杂的程序。

Page 2: 第 15 章  进程控制

15.1 进程的基本概念

在讨论进程的基本概念之前,我们首先介绍两种查看 Linux 系统中进程信息的方法。

Page 3: 第 15 章  进程控制

15.1.1 进程状态和状态转换

进程在生存周期中呈现出各种状态及状态的转换,这些信息反映了进程的获取系统资源的情况。 Linux 系统的进程状态模型见表 15.1 所示。

Page 4: 第 15 章  进程控制

15.1.1 进程状态和状态转换1 .子进程被 Linux 内核调入 CPU 执行的过程

Page 5: 第 15 章  进程控制

15.1.1 进程状态和状态转换

2 .子进程进入睡眠状态

Page 6: 第 15 章  进程控制

15.1.1 进程状态和状态转换

3 .子进程结束

Page 7: 第 15 章  进程控制

15.1.2 进程控制

在 Linux 系统中,用户创建子进程的惟一方法就是使用 fork 系统调用。 fork 系统调用的流程如图 15.5 所示。

Page 8: 第 15 章  进程控制

15.1.3 进程调度

Linux 系统进程调度包括两个概念,分别是调度时机和调度算法。调度时机指进程何时被调度上 CPU 执行。例如,转变为睡眠状态的进程将获得较高的优先级,一但所需要的资源被释放,该进程可以立即被调度上 CPU 执行。被抢占的进程也将获得一个较高的优先级,抢占其 CPU 时钟周期的进程一旦转为用户状态,被抢占的进程立即转为内核状态。调度算法所关心的内容就是如何为进程分配优先级。

Page 9: 第 15 章  进程控制

15.2 进程基本操作

本节将通过介绍关于进程操作的系统调用函数来讲解进程的基本操作方法,其中包括 fork 调用、 exec 调用、 exit调用、 wait 调用和 sleep 调用,相关函数被定义在系统调用库“ unistd.h” 中。通过本节,我们将了解如何产生子进程,进程如何改变它的执行映像,父子进程的同步等操作。由此也了解到一些并行程序的基本概念与如何设计简单的并行程序。

Page 10: 第 15 章  进程控制

15.2.1 fork 系统调用

fork 系统调用有两个函数,分别是 fork() 函数和 vfork() 函数。 fork 系统调用可创建一个子进程,该调用的一般形式是:

pid_t fork(void);

pid_t vfork(void);

Page 11: 第 15 章  进程控制

15.2.2 exec 系统调用

系统调用 exec 以新进程替代原有进程,但是 PID 保持不变。因此可以认为, exec 系统调用实际上没有创建新进程,只是替换了原有进程上下文的内容。

Page 12: 第 15 章  进程控制

15.2.3 exit 系统调用

系统调用 exit 的功能是终止发出调用的进程,它包含两个函数,分别是 _exit() 函数和 exit 函数。它们的一般形式如下:

void _exit(int status);

void exit(int status);

系统调用 _exit() 立即终止发出调用的进程。所有属于该进程的文件描述符都关闭。如果该进程拥有子进程,那么父子进程关系被转到 init 进程上。被结束的进程将收到来自子进程的僵死信号 SIGCHLD 。如果被结束的进程在控制台或终端上运行, shell 程序将收到 SIGHUP 信号。

Page 13: 第 15 章  进程控制

15.2.4 wait 系统调用

系统调用 wait 用于父进程与子进程同步。父进程调用后,将进入睡眠状态,直到子进程结束或者父进程在被其他进程终止。使用 wait 系统调用需要包含头文件“ sys/types.h” 和“ sys/wait.h” 。

Page 14: 第 15 章  进程控制

15.2.5 sleep 函数调用

系统调用 sleep 用来使进程主动进入睡眠状态,该函数的一般形式是:

sleep(秒数 );

执行该系统调用后,进程将进入睡眠状态,直到指定的秒数已到。正常情况下,该调用的返回值为 0 ,若是因为被信号所唤醒,则返回值为原始秒数减去已睡眠秒数的差。

Page 15: 第 15 章  进程控制

15.3 进程的特殊操作

上一节介绍了有关进程的一些基本操作,如进程的产生、进程的终止、进程执行映像的改变、等待子进程终止等。本节要介绍一些有关进程的特殊操作。有了这些操作,就使得进程的编程更加完善,能编制更为实用的程序。主要的内容有得到关于进程的各种 ID 、对进程的设置用户 ID 、改变进程的工作目录、根交换和改变进程的优先级等操作。

Page 16: 第 15 章  进程控制

15. 3.1 获得进程 ID

获得运行进程的 GID 可使用 getgid() 函数,获得运行进程的 EGID 可使用 getegid() 函数。标识 GID 与 EGID 的不同是由于执行文件设置 set-gid位引起的。

注意: GID 和 PGID 的区别是,一般执行该进程的用户的组 ID 就是该进程的 GID ,如果该执行文件设置了 set_gid位,则文件所群组 ID 就是该进程的 GID 。一个进程在 shell 下执行, shell 程序就将该进程的 PID 作为该进程组 PGID ,从该进程派生的子进程都拥有父进程所属进程组 PGID,除非父进程将子进程的 PGID 设置成与该子进程的 PID 一样。

Page 17: 第 15 章  进程控制

15.3.2 setuid 和 setgid 系统调用

设置进程的 UID 可使用 setuid() 函数,设置进程的 GID 可使用 setgid() 函数。

setuid() 函数可修改发出调用进程的 UID ,参数 uid 为创建进程的用户信息。如果以普通用户的 UID 作为参数执行该调用, Linux 内核将直接设置进程 UID 为参数 uid 信息。如果以根用户的 UID 作为参数,为了保障系统的安全性, Linux 内核将以进程表和 u区中用户真实的标识号来设置进程UID 。 setuid() 函数执行成功时,返回值为 0 ,否则返回 -1。

setgid() 函数可修改发出调用进程的 GID ,与前者不同,该调用不会检验用户的真实身份。参数 gid 为进程的新 GID 信息。执行成功时,返回值为 0 ,否则返回 -1 。

Page 18: 第 15 章  进程控制

15.3.3 setpgrp 和 setpgid 系统调用

系统调用 setpgrp() 和 setpgid() 都是用来设置进程 PGID ,它们的一般形式为:

int setpgrp(void);

int setpgid(pid_t pid, pid_t pgid);

其中, setpgrp() 函数直接将进程的 PGID 设为与 PID 相同的数值, setpgid() 以其中参数修改 PGID 。参数 pid 为指定进程的 PID ,值为 0 时修改发出调用进程的 PGID 。参数 pgid 为指定的 PGID 信息,值为 0 时,修改所有 PID 与参数 pid 相等的进程,将这些进程的 PGID值设为参数 pgid 的值。若以普通用户权限发出此调用,而 PGID 原本为根用户组所有,那么只有在指定进程与调用进程的 EUID 相同时,或者指定进程为调用进程的子进程时才有效。

Page 19: 第 15 章  进程控制

15.3.4 chdir 系统调用

在文件操作部分曾介绍过 chdir() 系统调用,该调用对于进程控制有不同的意义。 chdir() 函数将进程的当前工作目录改为由参数指定的目录。该调用的一般形式如下:

int chdir(const char *path);

参数 path 为指定目录的路径,发出该调用的进程必须具备该目录的执行权限。调用成功时返回值为 0 ,否则返回-1 ,并设置相应的错误代码。

Page 20: 第 15 章  进程控制

15.3.5 chroot 系统调用

系统调用 chroot又被称为根交换操作,作用通常是在一个 Linux 系统上虚拟另一个 Linux 系统,根交换后,所有的命令操作都被重新定向。该调用的一般形式如下:

int chroot(const char *path);

参数 path 为新的根目录路径,执行后,进程将以该目录作为根目录,并且使进程不能访问该目录以外的内容。该操作不改变当前工作目录,如果当前工作目录在指定目录以外,则无法访问其中内容。根交换操作只能由根用户发出,调用成功时返回值为 0 ,错误时返回 -1 ,并设置相应的错误代码。

Page 21: 第 15 章  进程控制

15.3.6 nice 系统调用

系统调用 nice() 用来改变进程的优先级。该调用的一般形式如下:

int nice(int inc);

参数 inc 为调用 nice() 函数的进程优先级数值的增量。优先级数值越低的值,被调度上 CPU 运行的机会越大;优先级数值越高,被调度上 CPU 运行的机会越低。但是,只有根用户能为 inc参数设置负值,使进程优先级提高,普通用户设置的正值会降低优先级。调用成功时,返回值为 0 ,否则返回 -1 。

Page 22: 第 15 章  进程控制

15.4 小结

本章介绍了进程的基本概念和基本操作方法,讲解了与进程操作有关的 Linux 系统调用函数。进程操作涉及到许多操作系统和 Linux 内核方面的知识,读者不能理解时,请查阅操作系统相关的理论书籍。进程控制对于发布大型软件非常有用,将程序实现不同功能的代码分开编译为可执行文件,实现分而治之的思想。用一个主控制程序调用其他的程序,每个可执行文件的大小都有限,不用一次将所有程序调入内存。通过网络对软件升级时,每次也只用从网络传输被改动的可执行文件,保证了升级过程的平稳过渡。