来晚了!
分组: | 实验室: | 指导教师: | 实验日期: | |
实验的准备阶段 (指导教师填写) | 课程名称 | 计算机操作系统 | ||
实验名称 | 处理处理机调度算法 | |||
实验目的 | (1)理解处理机算法的工作原理。 (2)掌握调度算法的实现、进程的状态以及状态转换。 | |||
实验内容 | 时间片轮转算法(模拟) 1、用到的数据结构 /* PCB */ struct PCB { pid_t pid;//进程PID int state; //状态信息,1表示正在运行,0表示暂停,-1表示结束 unsigned long runned_time;//已运行时间 unsigned long need_running_time;//剩余运行时间 }; /* PCB集合 */ struct PCB pcb[TOTAL]; //PCB集合 2、算法思路 算法实现分主函数(main)和分派函数(Dispatch)。 (1)其中主函数(main)的核心功能为: 实现6个子进程的创建和子进程PCB的初始化。对子进程PCB初始化时,状态设为0,运行时间由随机数产生。子进程创建后,就通过信号SIGSTOP让它处于暂停状态,当被分派函数(Dispatch)选中后,才能继续执行,输出子进程**正在执行的信息。 同时要在主程序里设置定时器,定时器的时间间隔为时间片长度,时间片到,就调用分派函数(Dispatch)重新选派程序。
将正在执行的子进程暂停,状态变为0,修改已运行时间和剩余运行时间。 如果该子进程剩余时间小于零,说明执行完毕,PCB状态改为-1,结束该子进程。 如果所有子进程都都结束,则程序结束。 重新选择下一个子进程,状态变为1,输出该子进程的已运行时间和剩余运行时间,让该子进程恢复运行。 | |||
实验类型 (打R) | ☑验证性 □演示性 ☑设计性 □综合性 | |||
实验的重点、难点 | 时间片轮转调度算法的实现 | |||
实验环境 | VMWare、RedHat Linux | |||
实验的实施阶段 | 实验步骤及实验结果 | 实验环境:centos 7 代码实现: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/time.h> #define TOTAL 6 #define TIME_QUANTUM 3 struct PCB { pid_t pid; int state; unsigned long runned_time; unsigned long need_running_time; }; struct PCB pcb[TOTAL]; void Dispatch(int signum) { int i; for (i = 0; i < TOTAL; ++i) { if (pcb[i].state == 1) { printf("进程 %d 正在运行。\n", pcb[i].pid); pcb[i].runned_time += TIME_QUANTUM; pcb[i].need_running_time -= TIME_QUANTUM; if (pcb[i].need_running_time <= 0) { printf("进程 %d 完成。\n", pcb[i].pid); pcb[i].state = -1; } else { printf("进程 %d - 已运行时间:%lu,剩余运行时间:%lu\n", pcb[i].pid, pcb[i].runned_time, pcb[i].need_running_time); pcb[i].state = 0; } int next = (i + 1) % TOTAL; while (pcb[next].state == -1) { next = (next + 1) % TOTAL; } printf("选择下一个进程:%d\n", pcb[next].pid); pcb[next].state = 1; kill(pcb[next].pid, SIGCONT); break; } } if (i == TOTAL) { printf("所有进程完成。\n"); exit(0); } } int main() { int i; struct sigaction sa; sa.sa_handler = Dispatch; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGALRM, &sa, NULL); srand(time(NULL)); for (i = 0; i < TOTAL; ++i) { pcb[i].pid = fork(); if (pcb[i].pid == 0) { // 子进程 pcb[i].state = 0; pcb[i].runned_time = 0; pcb[i].need_running_time = rand() % 20 + 1; // 随机运行时间 signal(SIGSTOP, SIG_IGN); // 忽略子进程的 SIGSTOP 信号 while (1); // 子进程保持运行直到被调度选择 } else if (pcb[i].pid > 0) { // 父进程 pcb[i].state = 0; kill(pcb[i].pid, SIGSTOP); // 暂停子进程 } } // 设置定时器 struct itimerval timer; timer.it_interval.tv_sec = TIME_QUANTUM; timer.it_interval.tv_usec = 0; timer.it_value.tv_sec = TIME_QUANTUM; timer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &timer, NULL); while (1); // 父进程持续运行直到所有子进程完成 return 0; } 运行结果: | ||
实验结果的处理阶段 | 实验结果的分析与总结 | 我通过观察和分析调度算法的执行情况以及子进程的行为,深入了解时间片轮转调度算法的工作原理和特性,并对系统调度器的行为有更清晰的认识。通过这个实验,我进行了以下操作:
我了解了进程的切换和调度,我关注进程之间的切换过程,观察被选中的下一个进程是如何被调度执行的,以及当所有进程执行完毕时,程序是如何结束的。 4. 我明白了定时器的作用,观察了调度器在执行过程中的效率,如进程切换的次数和开销。 |