进程控制(2)竞争条件 当多个进程都企图对共享数据进行某种处理,而最后的结果又取决于进程运行的顺序,则我们认为这发生了竞争条件。 如果一个父进程希望等待一个子进程终止,则它必须调用一种wait函数。如果一个进程要等待其父进程终止,可使用下列形式循环 while(getppid()!= 1) sleep(1); 这种形式的循环(成为轮询)的问题是它浪费了CPU时间。 为避免竞争条件和轮询,可以使用信号机制,也可以使用各种形式的进程间通信(IPC)。 exec函数当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。因为调用exec并不是创建进程,所以前后的进程ID并未改变。exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈。 有六种exec函数可供使用,他们常常被称为exec函数。 #include <unistd.h> int execl(const char *path, const char*arg, ...); int execlp(const char *file, const char*arg, ...); int execle(const char *path, const char*arg,..., char * const envp[]); int execv(const char *path, char *constargv[]); int execvp(const char *file, char *constargv[]); int execve(const char *filename, char*const argv[],char *const envp[]); 这6个函数中只有execve是内核的系统调用,另外5个只是库函数,他们最终都要调用该系统调用。 在执行exec前后,实际用户ID和实际中ID保持不变,而有效ID是否改变则取决于所执行程序文件的设置用户ID位和设置组ID位是否设置。如果新程序的设置用户ID位已设置,则有效用户ID编程程序文件所有者ID,否则有效用户ID不变。 更改用户ID和组ID#include <sys/types.h> #include <unistd.h> int setuid(uid_t uid); int setgid(gid_t gid); setuid函数可以设置实际用户ID、有效用户ID。 setgid函数可以设置实际组ID、有效组ID。 #include <sys/types.h> #include <unistd.h> int setreuid(uid_t ruid, uid_t euid); int setregid(gid_t rgid, gid_t egid); 上面两个函数的功能是交换实际用户ID和有效用户ID,交换实际组ID和有效组ID。 #include <sys/types.h> #include <unistd.h> int seteuid(uid_t euid); int setegid(gid_t egid); 上面两个函数值更改有效用户ID和有效组ID。 进程会计多数UNIX系统提供一个选项以进行进程会计处理。启动该选项后,每当进程结束时内核就写一个会计记录。电信的会计记录包含总量较小的二进制数据,一般包括命令名。所使用的CPU时间总量、用户ID和组ID。 下面这个函数用于启动和禁止进程会计 #include<unistd.h> int acct(constchar *filename); 进程时间当度量一个进程的执行时间时,UNIX系统使用三个进程时间值: 时钟时间、用户CPU时间和系统CPU时间。 时钟时间又称为墙上时间:它是进程运行的时间总量,其值与系统中同时运行的进程数有关。 用户CPU时间:执行用户指令所用的时间。 系统CPU时间是为该进程执行内核程序锁经历的时间。 用户CPU时间和系统CPU时间之和常被称为CPU时间。 #include <sys/times.h> clock_t times(struct tms *buf); 任一进程都可调用times函数以获得它自己及终止子进程的三个进程时间值。此函数填写由buf指向tms结构,该结构定义如下: struct tms { clock_t tms_utime; /* user time */ clock_t tms_stime; /* system time */ clock_t tms_cutime; /* user timeof children */ clock_t tms_cstime; /* systemtime of children */ }; 此结构没有包含墙上时钟时间的任何测试值。作为替代,times函数返回墙上时钟时间作为其函数值。调用两次times,用后一次的返回值减去前一次的返回值,所得的差值就是墙上时钟时间。 system函数#include <stdlib.h> int system(const char *command); system函数通过fork创建的子进程来用exec函数调用command,而父进程wait函数等待的这一过程,来执行命令command系统命令。
|