zsj2739 发表于 2021-11-27 19:06

【C语言】【分享】操作系统 时间片轮转模拟

两个正确的时间片轮转算法模拟(经测试,在特殊情况-'时间片为1时'也是正确的)
测试结果放在注释当中

代码1

#include<stdio.h>
#define N 50
struct PCB
{
        int pn;   //process name进程名字
        int at;   //arrival time到达时间
        int st;   //service time服务时间
        int ct;   //completion time完成时刻
        int sc;//sign completion标志是否完成
        int st1;//剩余服务时间
}process;

int sjp(int n)
{
        int i, j, T;
        printf("\n请输入时间片:\n");
        scanf("%d", &T);
        for (i = 1; i <= n; i++)      //收集进程信息
        {
                process.sc = 0;
                printf("\n%d:\n请依次输入进程的信息\n请输入pn:", i);
                scanf("%d", &process.pn);
                printf("请输入at:");
                scanf("%d", &process.at);
                printf("请输入st:");
                scanf("%d", &process.st);
                process.st1 = process.st;
        }
        for (i = 1; i <= n; i++)
                for (j = i + 1; j <= n; j++)   //按照各进程到达时间升序,对进程排序 注意:稳定的排序
                {
                        if (process.at < process.at)
                        {
                                process = process;
                                process = process;
                                process = process;
                        }
                }
        //for(i=1;i<=n;i++)    //检查排序是否正确
        //printf("%d\t",process.pn);

        int time = process.at;      //当前时间的初值
        int flag = 1;
        int sum = 0;                                        //记录完成的进程数
        printf("\n第几次调度进程 运行的进程pn 开始运行时间 运行时间 剩余服务时间 结束时间\n");
        int z = 1;   //记录第几次调度进程

        while (sum < n)
        {
                flag = 0;             //标志就绪队列中是否还有进程
                for (i = 1; i <= n; i++)    //时间片轮转法执行各进程
                {
                        if (process.sc == 1) continue;//已完成的进程
                        else
                        {
                                if (process.st1 <= T && time >= process.at)//未完成的进程但是还需服务的时间少于等于一个时间片
                                {
                                        flag = 1;
                                        time = time + process.st1;
                                        process.sc = 1;
                                        process.ct = time;
                                        printf("%8d%12d%15d%11d%11d%11d\n", z++, process.pn, time - process.st1, process.st1, 0, time);
                                        process.st1 = 0;
                                }

                                else if (process.st1 > T&&time >= process.at)//未完成的进程但其还需服务时间至少大于一个时间片
                                {
                                        flag = 1;
                                        time = time + T;
                                        process.st1 -= T;
                                        printf("%8d%12d%15d%11d%11d%11d\n", z++, process.pn, time - T, T, process.st1, time);
                                }
                                if (process.sc == 1) sum++;   //一个进程执行完就+1
                        }
                }

                if (flag == 0 && sum < n)   // 还有没执行的进程,且没进入就就绪队列
                {
                        for (i = 1; i <= n; i++)
                                if (process.sc == 0) { time = process.at; break; }
                }
        }
        return 0;
}

int main()
{
        int n;
        printf("\t\t时间片轮转调度算法\n");
        printf("请输入总进程数:\n");
        scanf("%d", &n);
        sjp(n);
        return 0;
}


/*

                时间片轮转调度算法
请输入总进程数:
5

请输入时间片:
1

1:
请依次输入进程的信息
请输入pn:1
请输入at:0
请输入st:4

2:
请依次输入进程的信息
请输入pn:2
请输入at:1
请输入st:3

3:
请依次输入进程的信息
请输入pn:3
请输入at:2
请输入st:5

4:
请依次输入进程的信息
请输入pn:4
请输入at:3
请输入st:2

5:
请依次输入进程的信息
请输入pn:5
请输入at:4
请输入st:4

第几次调度进程 运行的进程pn 开始运行时间 运行时间 剩余服务时间 结束时间
       1         1            0          1          3          1
       2         2            1          1          2          2
       3         3            2          1          4          3
       4         4            3          1          1          4
       5         5            4          1          3          5
       6         1            5          1          2          6
       7         2            6          1          1          7
       8         3            7          1          3          8
       9         4            8          1          0          9
      10         5            9          1          2         10
      11         1             10          1          1         11
      12         2             11          1          0         12
      13         3             12          1          2         13
      14         5             13          1          1         14
      15         1             14          1          0         15
      16         3             15          1          1         16
      17         5             16          1          0         17
      18         3             17          1          0         18
*/
代码2
#include<stdio.h>
#define MAX 10
struct task_struct
{
        char name;         //进程名称


        float arrivetime;         //到达时间/
        float starttime;   //开始运行时间/
        float runtime;          //运行时间/
        float finishtime;      //运行结束时间/


        int runflag;          //调度标志/
        int startflag;   //是否为第一次开始调度
} tasks;
int counter; //实际进程个数/
int pinput();
int timecounter = 0;
int poutput(); //调度结果输出/
int time();
int charge();//判断是否所有的进程都被执行过


int time()
{
        float temp = 0;//用来记录时间片已用长度
        int i;
        int j = 0;
        int k = 0;


        struct task_structcopy_task;//备份
        for (i = 0; i < counter; i++)
        {
                copy_task = tasks;//对进程的初始化信息备份
        }


        temp = tasks.arrivetime;//temp=第一个进程的到达时间
        while (charge())//while条件,charge为0跳出(说明进程都已经全部执行完毕),为1进入(进程还未执行完毕,继续执行)
        {
                for (i = 0; i < counter; i++)
                {
                        if (tasks.arrivetime > temp)//如果第i个的到达时间大于第一个的到达时间,则将第i个的到达时间与temp交换,更新temp的记录,但是第一次运行的时候不走这一步
                        {
                                temp = tasks.arrivetime;
                        }
                        if (tasks.runflag == 0)//第i个进程还未结束
                        {
                                if (tasks.startflag == 0)//该条件成立则说明,该进程是第一次执行,记录开始执行时间
                                {
                                        tasks.starttime = temp;//第一个进程的到达时间为temp
                                        tasks.startflag = 1;//运行完上一步后记录该进程已经不是第一次运行了
                                }
                                if (tasks.runtime / timecounter > 1)//,运行时间除以时间片长度,说明至少有两倍的时间片未执行
                                {
                                        tasks.runtime = tasks.runtime - timecounter;//剩余运行时间就等于原来运行时间减去一个时间片长度
                                        temp = temp + timecounter;//temp继续记录已用的时间片长度
                                }
                                else if (tasks.runtime - timecounter == 0)//即运行时间除以时间片长度为1,该进程剩下的刚好是一个时间片长度,说明该进程只需在运行一一步就可以运行完毕
                                {
                                        temp = temp + timecounter;//temp加上最后一个时间片长度就为该进程的结束时间
                                        tasks.finishtime = temp;
                                        tasks.runflag = 1;//标记该进程已经执行完毕
                                        tasks.runtime = copy_task.runtime;//为了计算周转时间,运行时间从备份里面还原到最开始的运行时间
                                }
                                else//仅剩下不足一倍的时间片,则剩余运行时间除以时间片长度<1
                                {
                                        temp = temp + tasks.runtime;//剩余运行时间不够一个时间片长度,则结束时间等于temp加上该进程的运行时间
                                        tasks.finishtime = temp;
                                        tasks.runflag = 1;//标记该进程已经运行完毕
                                        tasks.runtime = copy_task.runtime;
                                }
                        }
                }
        }
        return 0;
}


int charge()//判断是否全部进程都执行完毕
{
        int k;
        int superflag = 0;//判断是否全部的进程都执行完毕
        for (k = 0; k < counter; k++)
        {
                if (tasks.runflag == 0)//只要
                {
                        superflag = 1;
                        return superflag;
                        break;
                }
                else
                {
                        superflag = 0;
                }
        }
        return superflag;
}


int pinput() //进程参数输入/
{
        int i;
        printf("请输入进程个数:\n");
        scanf("%d", &counter);
        printf("请输入时间片长度:\n");
        scanf("%d", &timecounter);
        for (i = 0; i < counter; i++)
        {
                printf("******************************************\n");
                printf("请输入进程名称、到达时间、运行时间:(中间用空格隔开)\n");
                scanf("%s%f%f", tasks.name, &tasks.arrivetime, &tasks.runtime);


                tasks.starttime = 0;
                tasks.finishtime = 0;
                tasks.runflag = 0;//运行是否结束
                tasks.startflag = 0;//是否首次被执行
        }
        return 0;
}


int poutput() //调度结果输出
{
        int i;
        float zztime = 0, f1, w = 0;
        printf("进程名 到达时间 运行时间 开始时间 结束时间 周转时间\n");
        for (i = 0; i < counter; i++)
        {
                f1 = tasks.finishtime - tasks.arrivetime;
                zztime += f1;
                printf("%s\t%5.3f\t%5.3f\t%5.3f\t %5.3f\t%5.3f\n", tasks.name, tasks.arrivetime, tasks.runtime, tasks.starttime, tasks.finishtime, f1);
        }
        printf("平均周转时间=%5.2f\n", zztime / counter);
        return 0;
}


void main()
{


        pinput();
        printf("时间片轮转算法。\n\n");
        time();
        poutput();
}


/*
请输入进程个数:
5
请输入时间片长度:
1
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
A 0 4
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
B 1 3
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
C 2 5
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
D 3 2
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
E 4 4
时间片轮转算法。

进程名 到达时间 运行时间 开始时间 结束时间 周转时间
A       0.000   4.000   0.000    15.000 15.000
B       1.000   3.000   1.000    12.000 11.000
C       2.000   5.000   2.000    18.000 16.000
D       3.000   2.000   3.000    9.0006.000
E       4.000   4.000   4.000    17.000 13.000
平均周转时间=12.20
*/

tlf 发表于 2021-11-27 19:21

阳光好青年 发表于 2021-11-27 19:22

可以 裸机用的上

测试学学 发表于 2021-11-27 19:29

厉害了,,可惜我看不懂啊

SuperYG 发表于 2021-11-27 19:33

感谢大佬

IT_YCU 发表于 2021-11-27 19:38

谢谢分享

好久丿好酒 发表于 2021-11-27 19:48

可以啊,明天去试试

sam喵喵 发表于 2021-11-27 20:24

感谢分享,回头跑一跑试试

AYaoCryForYou 发表于 2021-11-27 21:54

可以用在单片机吗

koopa 发表于 2021-11-28 15:20

不明觉厉。
页: [1] 2
查看完整版本: 【C语言】【分享】操作系统 时间片轮转模拟