《UNIX环境高级编程》读书笔记之进程控制

时间:2021-12-12 10:00:58

1.进程标识

每个进程都有非负整型标示的唯一进程ID。系统中有一些特殊的进程,如ID为0的进程为调度进程,常被称为交换进程(swapper)。进程ID为1的进程为init进程,此进程负责启动UNIX系统。init进程是一个普通的用户进程,但是它是以超级用户权限运行的。init进程会成为所有孤儿进程(父进程已死亡的进程)的父进程。

除了进程ID,UNIX进程还有其他一些标示符。他们可以通过下列函数得到:

#include<unistd.h>

pid_t getpid(void)//返回进程ID

pid_t getppid(void)//返回父进程的ID

uid_t getuid(void)//返回实际用户的ID

uid_t geteuid(void)//返回进程有效用户ID

gid_t getgid(void)//返回进程的实际组ID

get_t getegid(void)//返回进程有效组ID


2.已在运行的进程可以通过fork()创建子进程

由fork()函数创建的进程成为子进程。fork()函数被调用一次,但是返回两次。子进程的返回值为0,父进程的返回值为子进程的进程ID。

子进程和父进程继续执行fork调用后的指令。子进程取得父进程的数据空间以及栈和堆的副本(注意,子进程和父进程不共享这些存储区,它们各自保留这些数据的一份副本)。


3.文件共享

fork()的一个特性是父进程的所有打开的文件描述符都被复制到子进程中,需要注意的是,如果父进程的标准输出被重定向,则子进程的标准输出也别重定向。

《UNIX环境高级编程》读书笔记之进程控制


4.函数wait()和waitpid()

当进程调用wait()或者waitpid()函数时,可能出现以下三种状态:

(1)如果其所有子进程都还在运行,则阻塞。

(2)如果有一个子进程已终止,正在等待父进程获取其终止状态,则取得子进程的终止状态后返回。

(3)如果它没有任何子进程。则立即出错返回。

#include <sys/wait.h>

pid_t wait(int * statloc);

pid_t waitpid(pid_t pid,int * statloc,int options);

两个函数的区别如下:

(1)在一个子进程终止前,wait使其调用者阻塞,而waitpid有一选项,可以使调用者不阻塞。

(2)waitpid可以不等待在其调用之后的第一个终止程序,它有若干选项,可以控制它所要等待的进程。

waitpid中的pid参数做如下解释:

(1)pid==-1,等待任一子进程。在此种情况下,waitpid与wait相等。

(2)pid>0,等待进程id与pid相等的进程。

(3)pid==0,等待组ID等于调用进程组ID的任一子进程。

(4)pid<-1,等待组ID等于pid绝对值的任一子进程。

options参数有三个可选的参数:

《UNIX环境高级编程》读书笔记之进程控制

5.wait3(),wait4()

wait3()与wait4()相比于wait(),waitpid()提供多一个功能。它们允许返回进程使用资源的概况。

#include <sys/types.h>

#include <sys/wait.h>

#include <sys/time.h>

#include <sys/resource.h>

pid_t wait3(int *statloc,int options,struct rusage *rusage);

pid_t wait4(pid_t pid,int *statloc,int options,struct rusage *rusage);

资源统计信息包括用户CPU时间总量,系统CPU时间总量,缺页次数,接收到信号的次数等。

不同系统对wait系列函数的支持:

《UNIX环境高级编程》读书笔记之进程控制


6.函数exec

用fork()函数创建新的子进程后,子进程要调用exec函数来执行另一个程序。调用exec并不创建新进程,所以前后进程的ID并没有改变。exec只是用了一个硬盘上新程序替换了当前进程的正文段、数据段、堆段、栈段。

exec系列函数:

《UNIX环境高级编程》读书笔记之进程控制


区别:

(1)前四个取路径名做参数,后两个区文件名做参数。

(2)参数表的传递方式不同。execl,execlp,execle要求每个命令行参数在函数中单独声明为一个参数。另外的四个则先构造一个包含各参数的数组,将这个数组作为参数。

(3)以e结尾的三个函数可以传递一个指向环境字符串指针数组的指针。


7.函数system

#iclude <stdlib.h>

int system(const char * cmdstring);

如果cmdstring为一个空指针,则仅当system函数可用时返回0.这一特性可以用来判断system函数是否可用。

system在其实现中其实是调用了fork,exec,waitpid。


8.进程会计

大多数UNIX系统提供了一个选项以进行进程会计处理。启用该选项后,每当进程结束后,内核就写一个进程记录。会计记录一般包含命令名,使用的CPU时间总量,用户ID和组ID,启动时间等。

会计记录的基本样式如下:

《UNIX环境高级编程》读书笔记之进程控制

9.进程调度

进程可以以nice值选择以更低的优先级运行。只有特权进程允许提高调度的优先级。进程可以通过nice函数得到或者提高进程的优先级。

#include <unistd.h>

int nice(int incr);

getpriority函数可以像nice函数那样获取进程的nice值,还可以获取一组相关进程的nice值。

#include <sys/resource.h>

int getpriority(int which,id_t who);