山东大学软件学院操作系统实验三——进程调度算法实验

一、实验时间

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模式,这样程序就运行成功了

  • 15
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
3.4 独立实验 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 父进程收到 进程收到 由键盘 由键盘 Ctrl+CCtrl+C Ctrl+C 发 出的 SIGINT SIGINTSIGINTSIGINTSIGINT信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 1,子进程进程 收到 由键盘 由键盘 Ctrl+ZCtrl+Z Ctrl+Z发出的 SIG SIGTSTP STP信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 1。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值