用户标识和进程调度

任一进程都可以得到其实际用户 ID 和有效 ID 及组 ID。但有时希望找到运行该程序用户的的登录名。通常情况下可以调用 getpwuid(getuid()) 来得到,但如果一个用户有多个登录名,这些登录名又对应着同一个用户 ID(但登录 shell 不同)时,就可以考虑使用 getlogin 函数来获取此登录名。

#include <unistd.h>
char *getlogin(void);
/* 返回值:若成功,返回指向登录名字符串的指针;否则,返回 NULL */

如果调用此函数的进程没有连接到用户登录时所用的终端,则函数会失败。通常称这些进程为守护进程(daemon)。
给出了登录名,就可用 getpwnam 在口令文件中查找用户的相应记录,从而确定其登录 shell 等。

UNIX 系统历史上对进程提供的只是基于调度优先级的粗粒度的控制。进程可以通过增大 nice 值选择以更低优先级运行,而只有特权进程允许提高调度权限。Single UNIX Specification 中 nice 值的范围在 0~2*NZERO-1 之间,有些实现支持 0~2*NZERO(注意:定义 NZERO 的头文件因系统而异。Linux 3.2.0 还可以通过非标准的 sysconf 参数 _SC_NZERO 来访问 NZERO 值)。
进程可以通过 nice 函数获取或更改它的 nice 值,但无法影响任何其他进程的 nice 值。

#include <unistd.h>
int nice(int incr);
/* 返回值:若成功,返回新的 nice 值或 NZERO;否则,返回 -1 */

incr 参数被增加到调用进程的 nice 值上。如果它过大或过小,系统都会无声无息地把它降到最大合法值或提高到最小合法值。由于 -1 是合法的成功返回值,所以在调用 nice 函数之前需要清除 errno,在 nice 返回 -1 时需要检查它的值,以便确认是否是调用失败。
getpriority 函数也可以获取进程的 nice 值,还可以获取一组相关进程的 nice 值;setpriority 函数则可以为进程、进程组和属于特定用户 ID 的所有进程设置优先级。

#include <sys/resource.h>
int getpriority(int which, id_t who);
/* 返回值:若成功,返回 -NZERO~NZERO-1 之间的 nice 值;否则,返回 -1 */
int setpriority(int which, id_t who, int value);
/* 返回值:若成功,返回 0;否则,返回 -1 */

其中,which 参数可以取以下 3 个值之一:PRIO_PROCESS 表示进程,PRIO_PGRP 表示进程组,PRIO_USER 表示用户 ID。如果 which 作用于多个进程,则返回其中优先级最高的(最小的 nice 值)。who 参数选择感兴趣的一个或多个进程。如果 who 为 0,表示调用进程、进程组或者用户(取决于 which 参数的值)。value 参数会增加到 NZERO 上,然后变为新的 nice 值。
下面这个程序度量了调度进程 nice 值的效果:两个进程并行运行,各自增加自己的计数器。父进程使用了默认的 nice 值,子进程以调整后的 nice 值运行 10s 后,两个进程都打印各自的计数器并终止。通过比较不同 nice 值的进程的计数值的差异就可以了解 nice 值是如何影响进程调度的。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>

unsigned long long count;
struct timeval end;

void checktime(char *str){
struct timeval tv;
gettimeofday(&tv, NULL);
if(tv.tv_sec>=end.tv_sec && tv.tv_usec>=end.tv_usec){
printf("%s count = %lld\n", str, count);
exit(0);
}
}

int main(int argc, char *argv[]){
pid_t pid;
char *s;
int nzero, ret;
int adj = 0;

setbuf(stdout, NULL); // disabled the buffer on stdout
#if defined(NZERO)
nzero = NZERO;
#elif defined(_SC_NZERO)
nzero = sysconf(_SC_NZERO);
#else
#error NZERO undefined
#endif
printf("NZERO = %d\n", nzero);
if(argc == 2)
adj = strtol(argv[1], NULL, 10);
gettimeofday(&end, NULL);
end.tv_sec += 10; // run for 10 seconds

if((pid=fork()) < 0){
printf("fork failed\n");
}else if(pid == 0){
s = "child";
printf("current nice value in child is %d, adjusting by %d\n", nice(0)+nzero, adj);
errno = 0;
if((ret=nice(adj)) == -1 && errno != 0)
printf("child set scheduling priority error\n");
printf("now child nice value is %d\n", ret+nzero);
}else{
s = "parent";
printf("current nice value in parent is %d\n", nice(0)+nzero);
}
for(;;){
if(++count == 0){
printf("%s counter wrap quit\n", s);
exit(2);
}
checktime(s);
}
}

执行程序两次:一次用默认的 nice 值,另一次用最高有效 nice 值(最低调度优先级)。程序运行在单处理器 Linux 系统上,以显示调度程序如何在不同 nice 值的进程间进行 CPU 的共享。否则,对于有空闲资源的系统(如多处理器系统或多核 CPU),两个进程可能无需共享 CPU(运行在不同的处理器上),就无法看出具有不同 nice 值的两个进程的差异。

$ ./niceDemo.out # 默认 nice 值
NZERO = 20
current nice value in parent is 20
current nice value in child is 20, adjusting by 0
now child nice value is 20
parent count = 125786180
child count = 125607852 # 可见同父进程平等调度

$ ./niceDemo.out 20 # 最高 nice 值
NZERO = 20
current nice value in parent is 20
current nice value in child is 20, adjusting by 20
now child nice value is 39
parent count = 229924425
child count = 3317494 # 可见 CPU 占比远低于父进程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值