UNIX高级环境编程(11)进程控制(Process Control)- 进程快照,用户标识符,进程调度
1 进程快照(Process Accounting)
当一个进程终止时,内核会为该进程保存一些数据,包括命令的小部分二进制数据、CPU time、启动时间、用户Id和组Id。这样的过程称为process accounting,本篇译为进程快照。
函数acct可以打开或关闭进程快照功能。
负责记录快照的数据结构如下所示:
成员说明:
- ac_flag成员记录进程执行过程中的特定事件(稍后的表中会详细说明);
- 进程创建时,初始化进程快照的数据在进程表(process table)中,但是只有在进程终止才会写进程快照。这样的机制导致了两个结果:
- 如果进程不终止,我们无法获取进程快照
- 进程快照文件的顺序依赖于进程终止的顺序,而不是进程被创建的顺序
- 进程快照对应一个进程,而不是程序。进程快照在进程被创建(fork)的时候被初始化,而不是程序被执行时,所以如果我们有一个程序链:A execs B, B execs C然后C退出,则只有一个进程快照被保存。命令的名字是程序的C决定,而CPU时间这类信息则是ABC的总和。
ac_flag不同的取值代表的事件含义如下表所示:
2 用户标识符(User Identification)
进程可以知道它的真实用户和组(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
函数细节:
- 如果进程并没有和一个终端关联,即没有一个登录用户,则该函数失败,不和终端关联的进程被称为daemon
- 有了登录用户名,我们可以在password文件中找到该用户,然后确定登录终端,例如使用getpwnam函数。
3 进程调度(Process Scheduling)
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
函数说明:
- 函数的作用是将当前进程的nice值加上参数incr作为新的nice值。
- 如果incr的值太大,则系统会自动将结果调整为最大的有效值;
- 如果incr的值太小,则系统会自动将结果调整为最小的有效值,即-1。
- 因为-1是一个合法的返回值,所以判断nice函数是否成功调用需要同时判断函数返回值和errno。在调用nice函数之前将errno清0。如果返回值为-1,errno为0.则调用成功,如果返回值和errno都为-1,则调用失败。
函数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);
}
小结
进程控制章节介绍了以下内容:
- fork
- exec
- _exit
- wait和waitpid
- system
- 解释器文件(interpreter files)和他们的工作原理
- 进程时间
下一章我们将会学习到进程关系(process relationship),关键字:sessions,job control。
参考资料:
《Advanced Programming in the UNIX Envinronment 3rd》
UNIX高级环境编程(11)进程控制(Process Control)- 进程快照,用户标识符,进程调度的更多相关文章
- UNIX高级环境编程1
UNIX高级环境编程1 故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表 ...
- Unix高级环境编程
[07] Unix进程环境==================================1. 进程终止 atexit()函数注册终止处理程序. exit()或return语句: ...
- UNIX高级环境编程(14)文件IO - O_DIRECT和O_SYNC详解 < 海棠花溪 >
春天来了,除了工作学习,大家也要注意锻炼身体,多出去运动运动. 上周末在元大都遗址公园海棠花溪拍的海棠花. 进入正题. O_DIRECT和O_SYNC是系统调用open的flag参数.通过指定o ...
- UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid
本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID 1 进程标识符(Process Identifie ...
- UNIX高级环境编程(12)进程关联(Process Relationships)- 终端登录过程 ,进程组,Session
在前面的章节我们了解到,进程之间是有关联的: 每个进程都有一个父进程: 子进程退出时,父进程可以感知并且获取子进程的退出状态. 本章我们将了解: 进程组的更多细节: sessions的内容: logi ...
- UNIX高级环境编程(8)进程环境(Process Environment)- 进程的启动和退出、内存布局、环境变量列表
在学习进程控制相关知识之前,我们需要了解一个单进程的运行环境. 本章我们将了解一下的内容: 程序运行时,main函数是如何被调用的: 命令行参数是如何被传入到程序中的: 一个典型的内存布局是怎样的: ...
- UNIX高级环境编程(15)进程和内存分配 < 故宫角楼 >
故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表和二叉树)分配额外内 ...
- UNIX高级环境编程(5)Files And Directories - 文件相关时间,目录文件相关操作
1 File Times 每个文件会维护三个时间字段,每个字段代表的时间都不同.如下表所示: 字段说明: st_mtim(the modification time)记录了文件内容最后一次被修改的时 ...
- unix高级环境编程学习笔记第七章(未完)
博客地址:http://www.cnblogs.com/zengjianrong/p/3222081.html 7.1 引言 Main函数调用:命令行参数:存储器布局:如何分配存储器:进程使用env: ...
随机推荐
- scala-02-基本数据类型-string-分支循环
一, 基本数据类型 1, scala的数据类型和java类似, 不同的是scala中所有的类型都是引用类型的 Byte Short Int Long Char Float Double String ...
- JVM内存初学 堆、栈、方法区
转自: http://www.open-open.com/lib/view/open1432200119489.html 这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解J ...
- windows环境下搭建Java开发环境(一):jdk安装和配置
一.资源下载 官网:http://www.oracle.com/technetwork/java/javase/downloads/index.html 本人安装的是jdk1.8,百度云资源:链接:h ...
- NYOJ 1013 除法表达式(欧几里德算法+唯一分解定理)
题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=1013 描述 给出一个这样的除法表达式:X1/X2/X3/···/Xk,其中Xi是 ...
- AutoMapper之嵌套映射
8.嵌套映射 嵌套映射就是一个类中包含有另一个类,这种情况下我们应该如何映射呢? /// <summary> /// 源对象 /// </summary> public cla ...
- css中添加屏幕自适应方法(rem)
css中添加屏幕自适应方法(rem) 只需要在公共css文件中添加下面代码:设计稿以750px,基础字体为20px为例,兼容性高,使用过程中px转化为rem即可 /*竖屏*/ @media scree ...
- C++虚析构函数解析
当派生类对象从内存中撤销时一般先运行派生类的析构函数,然后再调用基类的析构函数. 如果用new运算符建立的派生类的临时对象,对指向基类的指针指向这个临时对象当用delete运算符撤销对象时,系统执行的 ...
- SORT AGAIN(hdu2523)
SORT AGAIN Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 阿里数据源Druid配置详情
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-m ...
- pycharm虚拟环境
pycharm虚拟环境 1. 选择一个本地的空目录,---该目录就作为python虚拟环境目录, 2. 选择本地python安装目录: 3. 勾选该选项后则可以使用base interpreter中的 ...