日期:2014-05-16  浏览次数:20980 次

Linux/UNIX之进程控制(2)

进程控制(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系统命令。