Advanced Programming in UNIX Environment Episode 34

Process Scheduling

Historically, the UNIX System provided processes with only coarse control over their scheduling priority. The scheduling policy and priority were determined by the kernel. A process could choose to run with lower priority by adjusting its nice value (thus a process could be ‘‘nice’’ and reduce its share of the CPU by adjusting its nice value). Only a privileged process was allowed to increase its scheduling priority.

The real-time extensions in POSIX added interfaces to select among multiple
scheduling classes and fine-tune their behavior. We discuss only the interfaces used to adjust the nice value here; they are part of the XSI option in POSIX.1.

In the Single UNIX Specification, nice values range from 0 to (2*NZERO)−1,although some implementations support a range from 0 to 2*NZERO. Lower nice values have higher scheduling priority.

The real-time extensions in POSIX added interfaces to select among multiple scheduling classes and fine-tune their behavior.

In the Single UNIX Specification, nice values range from 0 to (2*NZERO)−1, although some implementations support a range from 0 to 2*NZERO. Lower nice values have higher scheduling priority.

Be aware that the header file defining NZERO differs among systems. In addition to the header file, Linux 3.2.0 makes the value of NZERO accessible through a nonstandard sysconf argument (_SC_NZERO).

A process can retrieve and change its nice value with the nice function.

#include <unistd.h>

int nice(int incr);

The getpriority function can be used to get the nice value for a process, just like the nice function.

#include <sys/resource.h>

int getpriority(int which, id_t who);

The setpriority function can be used to set the priority of a process, a process group, or all the processes belonging to a particular user ID.

#include <sys/resource.h>

int setpriority(int which,id_t who,int value);

The nice system call originated with an early PDP-11 version of the Research UNIX System. The getpriority and setpriority functions originated with 4.2BSD.

The Single UNIX Specification leaves it up to the implementation whether the nice value is inherited by a child process after a fork. However, XSI-compliant systems are required to preserve the nice value across a call to exec.

A child process inherits the nice value from its parent process in FreeBSD 8.0, Linux 3.2.0, Mac OS X 10.6.8, and Solaris 10.

#include "apue.h"
#include <errno.h>
#include <sys/time.h>

#if defined(MACOS)
#include <sys/syslimits.h>
#elif defined(SOLARIS)
#include<limits.h>
#elif defined(BSD)
#include <sys/param.h>
#endif

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);
        return 0;
    }
}

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

    setbuf(stdout, NULL);
#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;

    if((pid=fork())<0)
    {
        err_sys("fork failed");
    }
    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)
        {
            err_sys("child set scheduling priority");
        }
        printf("now child nice value is %d\n",ret+zero);
    }
    else
    {
        s=parent;
        printf("current nice value in parent is %d\n", nice(0)+nzero);
    }
    for(;;)
    {
        if(++count==0)
        {
            err_quit("%s counter wrap",s);
        }
        checktime(s);
    }
}

Evaluate the effect of changing the nice value

Process Times

Any process can call the times function to obtain these values for itself and any terminated children.

#include<sys/time.h>
clock_t times(struct tms *buf);

This function fills in the tms structure pointed to by buf :

struct tms {
    clock_t tms_utime; /* user CPU time */
    clock_t tms_stime; /* system CPU time */
    clock_t tms_cutime; /* user CPU time, terminated children */
    clock_t tms_cstime; /* system CPU time, terminated children */
};

All the clock_t values returned by this function are converted to seconds using the number of clock ticks per second—the _SC_CLK_TCK value returned by sysconf (Section 2.5.4).

Most implementations provide the getrusage(2) function. This function returns the CPU times and 14 other values indicating resource usage. Historically, this function originated with the BSD operating system, so BSD-derived implementations generally support more of the fields than do other implementations.

#include "apue.h"
#include <sys/time.h>

static void pr_times(clock_t, struct tms *, struct tms *);
static void do_cmd(char *);

int main(int argc, char *argv[])
{
    int i;

    setbuf(stdout, NULL)
    for(i=1;i<argc;i++)
        do_cmd(argv[i]);

    return 0;
}

static void do_cmd(char *cmd)
{
    struct tms tmstart, tmsend;
    clock_t start, end;
    int status;

    printf("\ncommand: %s\n",cmd);

    if((status=system(cmd))<0)
        err_sys("times error");
    if((status=system(cmd))<0)
        err_sys("system() error");
    if((end=times(&tmsend))==-1)
        err_sys("times error");

    pr_times(end-start,&tmsstart,&tmsend);
    pr_exit(status);
}

static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend)
{
    static long clktck=0;

    if(clktck==0)
        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);
}

Time and execute all command-line arguments

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值