题目描述
设有两个并发执行的父子进程,不断循环输出各自进程号、优先数和调度策略。进程初始调度策略均为系统默认策略和默认优先级。当某个进程收到 SIGINT 信号时会自动将其优先数加1,收到 SIGTSTP 信号时会自动将其优先数减 1。请编程实现以上功能。
实验思路
为父、子进程都注册优先级加一、减一的信号。响应信号改变优先级。
注意减优先级的操作必须在root用户下才有权限。
实验涉及的知识点
1、在linux系统中调度策略(policy)可以是以下3种:
a.SCHED_OTHER默认的分时调度策略(值等于0)
b.SCHED_FIFO先进先先出调度策略(值等于1)
c.SCHED_RR时间片轮转调度策略(值等于2)
后两种专用于对响应时间有特殊要求的进程,并且会抢先于SCHED_OTHER调度策略的进程而执行。一个具有SCHED_FIFO调度策略的进程只能被更高优先级的进程抢先,但具有SCHED_RR调度策略的进程必要时可以与同级进程共享时间片。
2、进程优先数(prio)由静态优先数和动态优先数两部分组成,值越小调度优先级越高。具有SCHED_OTHER策略的进程静态优先数总是0。动态优先数与进程的执行状态有关,但可以使用nice命令或系统调用加大进程优先数使其优先级降低,或用系统调用setpriority分别按进程或进程组或用户号设置介于-20到+20之间的动态优先数。
3、与进程调度策略有关的系统调用函数原型都声明在以下文件中:
#include <sched.h>
#include <sys/time.h>
#include <sys/resource.h>
4、设置进程调度策略的系统调用语法为:
int sched_setscheduler(pid_t pid,int policy,const struct sched_param *sp);
pid 进程号
policy以上说明的3种调度策略之一
sp调度参数结构指针,调度参数结构主要存有调度优先数
struct sched_param {
…
int sched_priority;
…
};
返回值: 执行成功后返回0
5、获取进程调度策略的系统调用语法为:
int sched_getscheduler(pid_t pid);
pid 进程号
返回值: 进程当前的调度策略
6、获取进程动态优先数的系统调用语法为:
int getpriority(int which,int who);
which设置的对象。可以是:
进程PRIO_PROCESS
进程组PRIO_PGRP
用户PRIO_USER
who对应设置对象的进程号或组号或用户号
返回值: 所有匹配进程中的最高优先数
7、设置进程动态优先数的系统调用语法为:
int setpriority(int which,int who,int prio);
which设置的对象。可以是:
进程PRIO_PROCESS
进程组PRIO_PGRP
用户PRIO_USER
who对应设置对象的进程号或组号或用户号
prio要设置的进程优先数
返回值: 所有匹配进程中的最高优先数
源代码
#include <sched.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// SIGINT 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程。
// SIGTSTP 停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号
typedef void (*sighandler_t)(int);
void sigcat_1()
{
printf("SIGINT信号,优先度加一\n");
setpriority(PRIO_PROCESS, getpid(), getpriority(PRIO_PROCESS, getpid()) + 1);
}
void sigcat_2()
{
printf("SIGTSTP信号,优先度减一\n");
setpriority(PRIO_PROCESS, getpid(), getpriority(PRIO_PROCESS, getpid()) - 1);
}
int main(int argc, char *argv[])
{
int i, j;
pid_t pid;
printf("Ctrl-C让进程优先度加一,Ctrl-Z让进程优先度减一\n");
pid = fork();
if (pid < 0)
{
fprintf(stderr, "fork failed");
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
signal(SIGINT, (sighandler_t)sigcat_1);
signal(SIGTSTP, (sighandler_t)sigcat_2);
for (i = 0; i < 20; i++)
{
printf("子进程 PID = %d 优先级= %d ,调度策略= %d\n", getpid(), getpriority(PRIO_PROCESS, 0), sched_getscheduler(getpid()));
sleep(1);
}
}
else
{
signal(SIGINT, (sighandler_t)sigcat_1);
signal(SIGTSTP, (sighandler_t)sigcat_2);
for (i = 0; i < 20; i++)
{
printf("父进程 PID = %d 优先级= %d ,调度策略= %d\n", getpid(), getpriority(PRIO_PROCESS, 0), sched_getscheduler(getpid()));
sleep(1);
}
}
}
}
}
}