实验内容:
实现时间片轮转算法(模拟),要求如下:
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)选中后,才能继续执行,输出子进程 x 正在执行的信息。
同时要在主程序里设置定时器,定时器的时间间隔为时间片长度,时间片到,就调用分派函
数(Dispatch)重新选派程序。
(2)分派函数的核心功能:
将正在执行的子进程暂停,状态变为 0,修改已运行时间和剩余运行时间。
如果该子进程剩余时间小于或等于 0,说明执行完毕,PCB 状态改为-1,结束该子进程。
重新选择下一个子进程,状态变为 1,输出该子进程的已运行时间和剩余运行时间,让该子
进程恢复运行。
当所有子进程都结束后,则父程序结束。
代码如下:文章来源:https://www.toymoban.com/news/detail-762739.html
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
//宏定义
#define TOTAL 6 //子进程总数
#define UNIT_TIME 200 //时间片长度(单位:毫秒)
#define UNIT_TICKS (UNIT_TIME * 1000) //计算时间片的ticks数
//进程状态
#define STATE_RUNNING 1
#define STATE_WAITING 0
#define STATE_FINISHED -1
void Dispatch(int signum);
/* 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集合
//主函数
int main(int argc, char *argv[])
{
//定义变量
int i, j;
//初始化随机数种子
srand((unsigned int)time(NULL));
//初始化PCB集合
for (i = 0; i < TOTAL; i++)
{
pcb[i].state = STATE_WAITING;
pcb[i].runned_time = 0;
pcb[i].need_running_time = rand() % 1000; //随机产生运行时间
}
//创建子进程
for (i = 0; i < TOTAL; i++)
{
if ((pcb[i].pid = fork()) == 0)
{
//子进程执行代码
while (1)
{
//处于暂停状态,等待信号
kill(getpid(), SIGSTOP);
//子进程结束
if (pcb[i].need_running_time == 0)
{
exit(0);
}
//打印子进程信息
printf("\n");
printf("子进程ID:%d\n", pcb[i].pid);
printf("已运行时间:%ld\n", pcb[i].runned_time);
printf("剩余运行时间:%ld\n", pcb[i].need_running_time);
//模拟运行
usleep(UNIT_TICKS);
pcb[i].runned_time++;
pcb[i].need_running_time--;
}
}
}
//设置定时器
struct itimerval itv;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = UNIT_TICKS;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = UNIT_TICKS;
setitimer(ITIMER_REAL, &itv, NULL);
//捕捉SIGALRM信号
signal(SIGALRM, Dispatch);
//等待子进程结束
for (i = 0; i < TOTAL; i++)
{
waitpid(pcb[i].pid, NULL, 0);
}
//程序结束
printf("\n程序执行结束!\n");
return 0;
}
//分派函数
void Dispatch(int signum)
{
//暂停正在执行的进程
int i;
for (i = 0; i < TOTAL; i++)
{
if (pcb[i].state == STATE_RUNNING)
{
kill(pcb[i].pid, SIGSTOP);
break;
}
}
//检查所有进程是否结束
int finished = 1;
for (i = 0; i < TOTAL; i++)
{
//如果剩余运行时间小于零,则说明该进程结束
if (pcb[i].need_running_time < 0)
{
pcb[i].state = STATE_FINISHED;
}
else if (pcb[i].state != STATE_FINISHED)
{
finished = 0;
}
}
//如果所有进程都结束,则停止定时器,结束程序
if (finished)
{
struct itimerval itv;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, NULL);
return;
}
//选择下一个要执行的进程
for (i = 0; i < TOTAL; i++)
{
//找到第一个状态为0的进程
if (pcb[i].state == STATE_WAITING)
{
pcb[i].state = STATE_RUNNING;
kill(pcb[i].pid, SIGCONT);
break;
}
}
}
上述代码的运行结果如下图:
可见,子进程id一直为0(这里有问题,请各位读者加以改正,有改正的方法可以在评论区评论一下),并且只会创建6个子进程。
如果还有好的方法我也会再分享出来。文章来源地址https://www.toymoban.com/news/detail-762739.html
到了这里,关于实现时间片轮转算法(模拟)计算机操作系统实验5:进程调度算法模拟-RR的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!