一、实验时间
2021年4月29日,星期四,第9周
二、实验说明
1.在linux系统中调度策略分为3种
- SCHED_OTHER:默认的分时调度策略,值为0
- SCHED_FIFO:先进先出调度,值为1
- SCHED_RR:轮转法调度,值为2
2.设置进程调度策略的系统调用语法
int sched_setscheduler(pid_t pid,int policy,const struct sched_param *sp);
- pid:进程号
- policy:三种调度策略之一
- sp:调度参数结构指针,里面有调度优先数
执行成功则返回0
3.获取进程调度策略的系统调用语法
int sched_getscheduler(pid_t pid);
- pid 进程号
返回值: 进程当前的调度策略
4.获取进程动态优先数的系统调用语法
int getpriority(int which,int who);
which代表设置的对象,which的值可以是
- 进程 PRIO_PROCESS
- 进程组 PRIO_PGRP
- 用户 PRIO_USER
who 对应设置对象的进程号或组号或用户号
返回值: 所有匹配进程中的最高优先数
5.设置进程动态优先数的系统调用语法
int setpriority(int which,int who,int prio);
which代表设置的对象,which的值可以是
- 进程 PRIO_PROCESS
- 进程组 PRIO_PGRP
- 用户 PRIO_USER
who 对应设置对象的进程号或组号或用户号
prio 要设置的进程优先数
返回值: 所有匹配进程中的最高优先数
三、示例实验
本例演示实验指导书上的示例实验
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/time.h>
#include <sys/resource.h>
int main(int argc, char *argv[])
{
int i,j,status;
int pid[3]; //存放进程号
struct sched_param p[3]; //设置调度策略时使用的数据结构
for(i=0; i<3;i++)
{
//循环创建3 个子进程
if((pid[i]=fork()) >0)
{
//取进程优先数放在调度策略数据结构中
p[i].sched_priority = (argv[i+1] != NULL) ? atoi(argv[i+1]):10;
//父进程设置子进程的调度策略.如果命令行第4,5,6 参数指定了3个策略值则按指定的数设置,否则都为默认策略
sched_setscheduler(pid[i],(argv[i+4] != NULL) ? atoi(argv[i+4]) : SCHED_OTHER,&p[i]);
//父进程设置子进程的优先数,如果命令行第1,2,3 参数指定了3个优先数则按指定的数设置,否则都为10
setpriority(PRIO_PROCESS,pid[i],(argv[i+1] != NULL) ? atoi(argv[i+1]):10);
}
//各子进程循环报告其优先数和调度策略
else
{
sleep(1);
//每隔1 妙报告一次进程号和优先级
for(i=0; i<10; i++)
{
printf("Child PID = %d priority = %d\n",getpid(),getpriority(PRIO_PROCESS,0));
sleep(1);
}
exit( EXIT_SUCCESS);
}
}
//父进程报告子进程调度策略后先行退出
printf("My child %d policy is %d\n",pid[0],sched_getscheduler(pid[0]));
printf("My child %d policy is %d\n",pid[1],sched_getscheduler(pid[1]));
printf("My child %d policy is %d\n",pid[2],sched_getscheduler(pid[2]));
return EXIT_SUCCESS;
}
通过这个实验,我们需要重点理解以下几个方法:
- 输出优先级的方法:getpriority(PRIO_PROCESS,int pid);
- 输出调度策略:sched_getscheduler(int pid);
- 设置优先级的方法:setpriority(PRIO_PROCESS,int pid,int prio);
四、实验要求
设有两个并发执行的父子进程,不断循环输出各自进程号、优先数和调度策略。
进程初始调度策略均为系统默认策略和默认优先级。当某个进程收到SIGINT信号时会自动将其优先数加1,收到SIGTSTP信号时会自动将其优先数减1。请编程实现以上功能。
要完成这个实验,我们需要熟悉以下几个方法
(1)输出进程号的方法:getpid();
(2)输出优先级的方法:getpriority(PRIO_PROCESS,int pid);
(3)输出调度策略:sched_getscheduler(int pid);
(4)设置优先级的方法:setpriority(PRIO_PROCESS,int pid,int prio);
还需要注意两个信号对应的是什么控制
- SIGINT信号:按下Ctrl+C时触发
- SIGTSTP信号:按下Ctrl+Z时触发
本次实验源代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sched.h>
#include <sys/time.h>
#include <sys/resource.h>
static int flag = 0;
//加信号
void add(int sig)
{
flag++;
}
//减信号
void minus(int sig)
{
flag--;
}
int main()
{
//绑定信号
signal(SIGINT,add);
signal(SIGTSTP,minus);
int pid = fork();
if(pid == 0)
{
while(1)
{
//设置进程的优先级
setpriority(PRIO_PROCESS,pid,flag);
//输出进程号
printf("child pid = %d\n",pid);
//输出优先级
printf("child process priority = %d\n",getpriority(PRIO_PROCESS,pid));
//输出调度策略
printf("child process scheduler = %d\n",sched_getscheduler(pid));
sleep(2);
}
}
else if(pid > 0)
{
while(1)
{
//设置进程的优先级
setpriority(PRIO_PROCESS,getpid(),flag);
//输出进程号
printf("parent pid = %d\n",getpid());
//输出优先级
printf("parent process priority = %d\n",getpriority(PRIO_PROCESS,getpid()));
//输出调度策略
printf("parent process scheduler = %d\n",sched_getscheduler(getpid()));
sleep(2);
}
}
}
程序运行结果如下
当按下Ctrl+C时,优先级+1。当按下Ctrl+Z时,优先级-1
五、注意事项
1.一开始在写程序的时候,按下ctrl+c能实现进程优先级+1,但按下ctrl+z时进程优先级不变,后来问了别人才知道只有切换到root权限之后才能实现进程优先级-1
2.打开终端,敲sudo su,之后输入密码即可切换到root模式,这样程序就运行成功了