當一個進程終止時,內核會為該進程保存一些數據,包括命令的小部分二進制數據、CPU time、啟動時間、用戶Id和組Id。這樣的過程稱為process accounting,本篇譯為進程快照。
函數acct可以打開或關閉進程快照功能。
負責記錄快照的數據結構如下所示:
成員說明:
ac_flag不同的取值代表的事件含義如下表所示:
進程可以知道它的真實用戶和組(real user ID and group ID),有效用戶和組(effective user ID and group ID)。
然后有時候我們想知道運行程序的登錄用戶名。函數getpwuid可以實現。
函數聲明:
#include <unistd.h>
char* getlogin(void);
// Returns: pointer to string giving login name if OK, NULL on error
函數細節:
nice值決定了進程的運行優先級。
取值范圍:0 ~ (2 * NZERO -1)
nice值越低,優先級越高。
意思就是:進程越好,進程的優先級越高。
nice值的默認值為NZERO。
函數nice可以獲取并修改nice值。
進程調用nice函數只能修改它自己的nice值。
函數聲明:
#include <unistd.h>
int nice(int incr);
// Returns: new nice value - NZERO if OK, -1 on error
函數說明:
函數getpriority可以用來獲取一個進程的nice值。
函數聲明:
#include <sys/resource.h>
int getpriority(int which , id_t who);
// Returns: nice value between -NZERO和NZERO-1之間 if OK, -1 on error
參數說明:
which:有三個可取值:PRIO_PROCESS表明是一個進程,PRIO_PGRP表明是一個進程組,PRIO_USER表明目標是一個用戶。
which參數的作用是控制who的含義,以及who參數如何選擇進程。
如果who取值為0,則函數返回當前調用進程、進程組或用戶的nice值。
如果which取值為PRIO_USER,who取值0,則返回當前進程的真實用戶ID(real user Id)。
如果which取值為PRIO_GROUP,則返回所有進程中priority最高,即nice值最低的進程的nice值。
設置nice值使用函數setpriority。
函數聲明:
#include <sys/resource.h>
int setpriority(int which, id_t who, int value);
參數的作用和getpriority相同。
value的值被加到nice默認值NZERO上,設置該值為新的nice值。
4 進程時間(Process Times)進程時間包括:墻上時間(wall clock tie),用戶CPU時間(user CPU time),內核CPU時間(system CPU time).
函數times可以獲取這三種時間。
函數聲明:
#include <sys/times.h>
clock_t times(struct tms *buf);
函數細節:
函數會向結構體struct tms類型的變量中填充上面的三個時間,struct tms結構體的聲明如下:
墻上時間為該函數的返回值。墻上時間為從過去某個時間點到現在的時間,所以不能直接作為時間來使用。
大多情況下,我們可以通過times的返回值來計算相對時間,例如,在進程開始和結束時分別調用times函數,然后相減來計算進程的運行時間。
兩個子進程時間變量用來保存父進程調用wait函數等待子進程退出的時間。
Example程序功能:執行命令行傳入的命令,計算每個命令執行的時間,并打印結構體tms中的成員值。
code
#include "apue.h"
#include <sys/times.h>
static void pr_times(clock_t, struct tms *, struct tms *);
staticvoid do_cmd(char *);
int
main(int argc, char *argv[])
{
int i;
setbuf(stdout, NULL);
for (i = 1; i < argc; i++)
do_cmd(argv[i]); /* once for each command-line arg */
exit(0);
}
staticvoid
do_cmd(char *cmd) /* execute and time the "cmd" */
{
struct tms tmsstart, tmsend;
clock_t start, end;
int status;
printf("/ncommand: %s/n", cmd);
if ((start = times(&tmsstart)) == -1) /* starting values */
err_sys("times error");
if ((status = system(cmd)) < 0) /* execute command */
err_sys("system() error");
if ((end = times(&tmsend)) == -1) /* ending values */
err_sys("times error");
pr_times(end-start, &tmsstart, &tmsend);
pr_exit(status);
}
staticvoid
pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend)
{
static long clktck = 0;
if (clktck == 0) /* fetch clock ticks per second first time */
if ((clktck = sysconf(_SC_CLK_TCK)) < 0)
err_sys("sysconf error");
printf(" real: %7.2f/n", real / (double) clktck);
printf(" user: %7.2f/n",
(tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck);
printf(" sys: %7.2f/n",
(tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck);
printf(" child user: %7.2f/n",
(tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck);
printf(" child sys: %7.2f/n",
(tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck);
}
運行結果:進程控制章節介紹了以下內容:
下一章我們將會學習到進程關系(process relationship),關鍵字:sessions,job control。
參考資料:
《Advanced Programming in the UNIX Envinronment 3rd》
新聞熱點
疑難解答