7 进程控制

7.1 进程标识

        每个进程都有一个非负整型的唯一进程ID。因为进程ID标识符总是唯一的,常将其用做其他标识符的一部分以保证其唯一性。

        有某些专用的进程:进程ID 0是调度进程,常常被称为交换进程(swapper)。该进程并不执行任何磁盘上的程序—它是内核的一部分,因此也被称为系统进程。进程ID 1通常是init进程,在自举过程结束时由内核调用。

        在某些UNIX的虚存实现中,进程ID 2是页精灵进程(pagedaemon)。此进程负责支持虚存系 统的请页操作。与交换进程一样,页精灵进程也是内核进程。

        除了进程ID,每个进程还有一些其他标识符。下列函数返回这些标识符。

#include <sys/types.h>
#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
gid_t getegid(void); //返回:调用进程的有效组ID

注意,这些函数都没有出错返回。

7.2 fork函数

        一个现存进程调用fork函数是UNIX内核创建一个新进程的唯一方法 (这并不适用于前节提及的交换进程、init进程和页精灵进程。这些进程是由内核作为自举过程的一部分以特殊方式创建的)。

#include <sys/types.h>
#include <unistd.h>

//返回:子进程中为0,父进程中为子进程ID,出错为-1
pid_t fork(void);

由fork创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是 0,而父进程的返回值则是新子进程的进程 ID。

        子进程和父进程继续执行 fork之后的指令。子进程是父进程的复制品。例如,子进程获得父进程数据空间、堆和栈的复制品。注意,这是子进程所拥有的拷贝。父、子进程并不共享这些存储空间部分。如果正文段是只读的,则父、子进程共享正文段。

7.3 vfork函数

        vfork与fork一样都创建一个子进程, 但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec (或exit ),于是也就不会存访该地址空间。

        vfork保证子进程先运行,在它调用exec或exit之后父进 程才可能被调度运行。

7.4 wait和waitpid函数

        当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件(这可以在父进程运行的任何时候发生 ),所以这种信号也是内核向父进程发的异步通知。父进程可以忽略该信号,或者提供一个该信号发生时即被调用执行的函数 (信号处理程序)。对于这种信号的系统默认动作是忽略它。调用wait或waitpid的进程可能会:

  • 阻塞(如果其所有子进程都还在运行)。
  • 带子进程的终止状态立即返回(如果一个子进程已终止,正等待父进程存取其终止状态 )。
  • 出错立即返回(如果它没有任何子进程)。

        如果进程由于接收到SIGCHLD信号而调用wait,则可期望wait会立即返回。但是如果在一 个任一时刻调用wait,则进程可能会阻塞。

#include <sys/types.h>
#include <sys/wait.h>

//两个函数返回:若成功则为进程 I D,若出错则为-1
pid_t wait(int *statloc) ;
pid_t waitpid(pid_t pid, int *statloc, int options) ;

这两个函数的区别是:

  • 在一个子进程终止前, wait 使其调用者阻塞,而 waitpid 有一选择项,可使调用者不阻 塞。
  • waitpid并不等待第一个终止的子进程—它有若干个选择项,可以控制它所等待的进程。

        如果一个子进程已经终止,是一个僵死进程,则 wait立即返回并取得该子进程的状态,否 则wait使其调用者阻塞直到一个子进程终止。如调用者阻塞而且它有多个子进程,则在其一个 子进程终止时,wait就立即返回。因为wait返回终止子进程的进程ID,所以它总能了解是哪一个子进程终止了。

        这两个函数的参数statloc是一个整型指针。如果statloc不是一个空指针,则终止进程的终止状态就存放在它所指向的单元内。如果不关心终止状态,则可将该参数指定为空指针。

wait和waitpid所返回的终止状态的宏
说明
WIFEXITED(status)

若为正常终止子进程返回的状态,则为真。对于这种情况可执行 WEXITSTATUS(status)

取子进程传送给exit或_exit参数的低8位

WIFSIGNALED(status)

若为异常终止子进程返回的状态,则为真(接到一个不捕捉的信号)。对于这种情况,可执行

WTERMSIG(status)

取使子进程终止的信号编号。 另外,

WCOREDUMP(status)

若已产生终止进程的core文件,则它返回真

WIFSTOPPED(status)

若为当前暂停子进程的返回的状态,则为真。对于这种情况,可执行

WSTOPSIG(status)

取使子进程暂停的信号编号

7.5 exec函数

        当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其 main函数开始执行。 因为调用exec并不创建新进程,所以前后的进程 ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。

        有六种不同的exec函数可供使用,它们常常被统称为exec函数。

#include <unistd.h>

//六个函数返回:若出错则为- 1,若成功则不返回
int execl(const char *pathname, const char * arg0, ... /* (char *) 0 */);

int execv(const char *pathname, char *const argv[] );

int execle(const char *pathname, const char * arg0, ... /* (char *)0, char *const envp[]*/);

int execve(const char *pathname, char *const argv[], char *const envp[] );

int execlp(const char *filename, const char * arg0, ... /* (char *) 0 */);

int execvp(const char *filename, char *const argv[] );

7.6 system函数

#include <stdlib.h>
int system(const char *cmdstring) ;

如果cmdstring是一个空指针,则仅当命令处理程序可用时, system返回非0值,这一特征可以决定在一个给定的操作系统上是否支持system函数。

        因为system在其实现中调用了fork、exec和waitpid,因此有三种返回值:

(1)如果fork失败或者waitpid返回除EINTR之外的出错,则system返回-1,而且errno中设置了错误类型。

(2)如果exec失败(表示不能执行shell ),则其返回值如同shell执行了exit(127)一样。

(3)否则所有三个函数( fork , exec和waitpid)都成功,并且system的返回值是shell的终止状态

7.7 进程时间

        墙上时钟时间、用户CPU时间和系统CPU时间。任一进程都可调用times函数以获得它自己及终止子进程的上述值。

#include <sys/times.h>

//返回:若成功则为经过的墙上时钟时间(单位:滴答),若出错则为-1
clock_t times(struct tms)* buf) ;

此函数填写由buf指向的tms结构,该结构定义如下:

struct tms
{
    clock_t tms_utime;   //user cpu time
    clock_t tms_stime;   //system cpu time
    clock_t tms_cutime;  //user cpu time, terminate children
    clock_t tms_cstime;  //system cpu time, terminate children
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值