操作系统4种进程调度算法(c语言)

目录

FCFS

SJF

HPF

RR


 

FCFS

FCFS(First-Come, First-Served)调度算法是一种最简单的进程调度算法,也被称为先来先服务算法。在这种算法中,进程按照它们到达就绪队列的顺序依次执行,即先到达的进程先执行,后到达的进程排队等待。
基本原则是按照进程到达的顺序,逐个地将它们分配给 CPU,直到所有进程都执行完毕。这意味着在FCFS算法中,不考虑进程的执行时间长短或优先级高低,仅仅按照它们进入就绪队列的先后顺序进行调度。
尽管FCFS算法简单,易于理解,但它也有一些缺点。其中一个主要问题是平均等待时间可能较长,尤其是当一些短进程在一些长进程之后到达时。这可能导致低效的利用 CPU 时间,因为较长的进程可能会占用 CPU 较长时间,而其他进程等待的时间较长。
FCFS算法是一种非抢占式调度算法,因为一旦进程开始执行,它将一直运行直到完成,或者直到被更高优先级的进程抢占。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义进程结构体
typedef struct
{
    char name[10];
    int enter_time;
    int running_time;
} Program;

// 定义就绪队列结构体
typedef struct
{
    Program **programs;
    int size;
    int capacity;
} ProgramQueue;

// 初始化就绪队列
void InitializeQueue(ProgramQueue *queue, int capacity)
{
    queue->programs = (Program **)malloc(capacity * sizeof(Program *));
    queue->size = 0;
    queue->capacity = capacity;
}

// 将进程加入队列
void EnterQueue(ProgramQueue *queue, Program *program)
{
    if (queue->size < queue->capacity)
    {
        queue->programs[queue->size] = program;
        queue->size++;
    }
}

// 从队列中取出进程
Program *PollQueue(ProgramQueue *queue)
{
    if (queue->size > 0)
    {
        Program *program = queue->programs[0];
        for (int i = 1; i < queue->size; i++)
        {
            queue->programs[i - 1] = queue->programs[i];
        }
        queue->size--;
        return program;
    }
    return NULL;
}

// 执行FCFS调度
void FCFS(Program pro[], int num)
{
    printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    // 按照到达时间排序

    ProgramQueue queue;
    InitializeQueue(&queue, num);
    EnterQueue(&queue, &pro[0]);
    int time = pro[0].enter_time;
    int pronum = 1;
    float sum_T_time = 0, sum_QT_time = 0;

    while (queue.size > 0)
    {
        Program *curpro = PollQueue(&queue);
        if (time < curpro->enter_time)
        {
            time = curpro->enter_time;
        }
        int done_time = time + curpro->running_time;
        int T_time = done_time - curpro->enter_time;
        sum_T_time += T_time;
        float QT_time = (float)T_time / curpro->running_time;
        sum_QT_time += QT_time;
        printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
        time += curpro->running_time;

        // 进程模拟执行过程
        while (pronum < num && pro[pronum].enter_time <= done_time)
        {
            EnterQueue(&queue, &pro[pronum]);
            pronum++;
        }
    }

    printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / num, sum_QT_time / num);
}

int main()
{
    int num = 3; // 假设有3个进程

    // 初始化进程数组
    Program pro[num];
    strcpy(pro[0].name, "P1");
    pro[0].enter_time = 0;
    pro[0].running_time = 5;

    strcpy(pro[1].name, "P2");
    pro[1].enter_time = 1;
    pro[1].running_time = 3;

    strcpy(pro[2].name, "P3");
    pro[2].enter_time = 3;
    pro[2].running_time = 6;

    // 调用FCFS函数
    FCFS(pro, num);

    return 0;
}

SJF

SJF (Shortest Job First) 是一种进程调度算法,它选择服务时间最短的进程来执行,以最小化平均等待时间。这是一种非抢占式的调度算法,即一旦进程开始执行,就一直执行到完成,除非有更短的作业进入就绪队列。
主要思想是通过预测进程的服务时间来选择下一个执行的进程,以确保总体上获得最短的作业完成时间。这样可以提高系统的吞吐量和响应速度。
SJF 可以分为两种类型:
1. 非抢占式 SJF: 一旦进程开始执行,就不会被中断,直到它完成。只有在进程完成后,系统才会选择下一个最短的作业。
2. 抢占式 SJF:允许更短作业中途插入执行。如果新进程的服务时间比当前正在执行的进程更短,那么系统会中断当前进程,转而执行新的进程。
实现 SJF 调度算法时,需要对进程按照服务时间进行排序,以便在选择下一个要执行的进程时能够方便地找到服务时间最短的进程。这通常通过使用排序算法(如快速排序或插入排序)来实现。需要注意的是,SJF 算法的一个问题是它对于长服务时间的进程可能会导致其他进程长时间等待,可能会出现饥饿(Starvation)的情况。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义进程结构体
typedef struct
{
    char name[10];
    int enter_time;
    int running_time;
} Program;

// 定义就绪队列结构体
typedef struct
{
    Program **programs;
    int size;
    int capacity;
} ProgramQueue;

// 初始化就绪队列
void InitializeQueue(ProgramQueue *queue, int capacity)
{
    queue->programs = (Program **)malloc(capacity * sizeof(Program *));
    queue->size = 0;
    queue->capacity = capacity;
}

// 将进程加入队列
void EnterQueue(ProgramQueue *queue, Program *program)
{
    if (queue->size < queue->capacity)
    {
        queue->programs[queue->size] = program;
        queue->size++;
    }
}

// 从队列中取出进程
Program *PollQueue(ProgramQueue *queue)
{
    if (queue->size > 0)
    {
        Program *program = queue->programs[0];
        for (int i = 1; i < queue->size; i++)
        {
            queue->programs[i - 1] = queue->programs[i];
        }
        queue->size--;
        return program;
    }
    return NULL;
}

// 按服务时间排序的比较函数
int CompareByRunningTime(const void *a, const void *b)
{
    return ((Program *)a)->running_time - ((Program *)b)->running_time;
}

// 执行SJF调度
void SJF(Program pro[], int num)
{
    printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");

    // 按照服务时间排序
    qsort(pro, num, sizeof(Program), CompareByRunningTime);

    ProgramQueue queue;
    InitializeQueue(&queue, num);
    int time = 0;
    int pronum = 0;
    float sum_T_time = 0, sum_QT_time = 0;

    while (pronum < num || queue.size > 0)
    {
        while (pronum < num && pro[pronum].enter_time <= time)
        {
            EnterQueue(&queue, &pro[pronum]);
            pronum++;
        }

        if (queue.size > 0)
        {
            Program *curpro = PollQueue(&queue);
            int done_time = time + curpro->running_time;
            int T_time = done_time - curpro->enter_time;
            sum_T_time += T_time;
            float QT_time = (float)T_time / curpro->running_time;
            sum_QT_time += QT_time;
            printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
            time += curpro->running_time;
        }
        else
        {
            time = pro[pronum].enter_time;
        }
    }

    printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / num, sum_QT_time / num);
}

int main()
{
    int num = 3; // 假设有3个进程

    // 初始化进程数组
    Program pro[num];
    strcpy(pro[0].name, "P1");
    pro[0].enter_time = 0;
    pro[0].running_time = 5;

    strcpy(pro[1].name, "P2");
    pro[1].enter_time = 1;
    pro[1].running_time = 3;

    strcpy(pro[2].name, "P3");
    pro[2].enter_time = 3;
    pro[2].running_time = 6;

    // 调用SJF函数
    SJF(pro, num);

    return 0;
}

HPF

高优先级先执行(High Priority First, HPF)调度算法是一种基于进程优先级的调度策略。该算法根据进程的优先级来决定下一个执行的进程。优先级越高的进程将优先执行,以确保更重要或紧急的任务能够尽快得到处理。
每个进程都被赋予一个优先级值,通常是一个整数。较小的优先级值表示较高的优先级,而较大的值表示较低的优先级。在每个调度点,系统选择具有最高优先级的就绪进程来执行。这确保了具有更高优先级的任务能够更快地获得处理。HPF 调度算法可以是抢占性的或非抢占性的。抢占性的 HPF 允许正在执行的进程被更高优先级的进程中断,以便立即执行更高优先级的任务。当进程到达时,将其插入到就绪队列中,按照优先级进行排序。具有更高优先级的进程将在队列的前部。在每个时间片或事件发生时,选择就绪队列中具有最高优先级的进程执行。执行完毕后,继续选择下一个最高优先级的就绪进程。
需要注意,过度依赖高优先级可能导致低优先级任务长时间等待,产生饥饿(starvation)现象。因此,在设计调度算法时,需要平衡对高优先级任务的服务和对低优先级任务的公平性。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义进程结构体
typedef struct
{
    char name[10];
    int enter_time;
    int running_time;
    int priority;
} Program;

// 定义就绪队列结构体
typedef struct
{
    Program **programs;
    int size;
    int capacity;
} ProgramQueue;

// 初始化就绪队列
void InitializeQueue(ProgramQueue *queue, int capacity)
{
    queue->programs = (Program **)malloc(capacity * sizeof(Program *));
    queue->size = 0;
    queue->capacity = capacity;
}

// 将进程加入队列
void EnterQueue(ProgramQueue *queue, Program *program)
{
    if (queue->size < queue->capacity)
    {
        queue->programs[queue->size] = program;
        queue->size++;
    }
}

// 从队列中取出进程
Program *PollQueue(ProgramQueue *queue)
{
    if (queue->size > 0)
    {
        Program *program = queue->programs[0];
        for (int i = 1; i < queue->size; i++)
        {
            queue->programs[i - 1] = queue->programs[i];
        }
        queue->size--;
        return program;
    }
    return NULL;
}

// 按优先级排序的比较函数
int CompareByPriority(const void *a, const void *b)
{
    return ((Program *)a)->priority - ((Program *)b)->priority;
}

// 执行HPF调度
void HPF(Program pro[], int num)
{
    printf("进程 到达时间 服务时间 优先级 开始时间 完成时间 周转时间 带权周转时间\n");

    // 按照优先级排序
    qsort(pro, num, sizeof(Program), CompareByPriority);

    ProgramQueue queue;
    InitializeQueue(&queue, num);
    int time = 0;
    int pronum = 0;
    float sum_T_time = 0, sum_QT_time = 0;

    while (pronum < num || queue.size > 0)
    {
        while (pronum < num && pro[pronum].enter_time <= time)
        {
            EnterQueue(&queue, &pro[pronum]);
            pronum++;
        }

        if (queue.size > 0)
        {
            Program *curpro = PollQueue(&queue);
            int done_time = time + curpro->running_time;
            int T_time = done_time - curpro->enter_time;
            sum_T_time += T_time;
            float QT_time = (float)T_time / curpro->running_time;
            sum_QT_time += QT_time;
            printf("%s\t%d\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, curpro->priority, time, done_time, T_time, QT_time);
            time += curpro->running_time;
        }
        else
        {
            time = pro[pronum].enter_time;
        }
    }

    printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / num, sum_QT_time / num);
}

int main()
{
    int num = 3; // 假设有3个进程

    // 初始化进程数组
    Program pro[num];
    strcpy(pro[0].name, "P1");
    pro[0].enter_time = 0;
    pro[0].running_time = 5;
    pro[0].priority = 3;

    strcpy(pro[1].name, "P2");
    pro[1].enter_time = 1;
    pro[1].running_time = 3;
    pro[1].priority = 1;

    strcpy(pro[2].name, "P3");
    pro[2].enter_time = 3;
    pro[2].running_time = 6;
    pro[2].priority = 2;

    // 调用HPF函数
    HPF(pro, num);

    return 0;
}

RR

轮转调度算法(Round Robin Scheduling)是一种常见的操作系统调度算法之一,它通过给每个进程分配一个时间片(时间量),然后按照轮转的方式依次执行每个进程,直到完成或者时间片用尽。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义进程结构体
typedef struct
{
    char name[10];
    int arrival_time;
    int burst_time;
    int remaining_time;
} Process;

// 定义就绪队列结构体
typedef struct
{
    Process **processes;
    int size;
    int capacity;
} ProcessQueue;

// 初始化就绪队列
void InitializeQueue(ProcessQueue *queue, int capacity)
{
    queue->processes = (Process **)malloc(capacity * sizeof(Process *));
    queue->size = 0;
    queue->capacity = capacity;
}

// 将进程加入队列
void EnterQueue(ProcessQueue *queue, Process *process)
{
    if (queue->size < queue->capacity)
    {
        queue->processes[queue->size] = process;
        queue->size++;
    }
}

// 从队列中取出进程
Process *PollQueue(ProcessQueue *queue)
{
    if (queue->size > 0)
    {
        Process *process = queue->processes[0];
        for (int i = 1; i < queue->size; i++)
        {
            queue->processes[i - 1] = queue->processes[i];
        }
        queue->size--;
        return process;
    }
    return NULL;
}

// 轮转调度函数
void RoundRobin(Process processes[], int num_processes, int time_slice)
{
    printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");

    // 初始化就绪队列
    ProcessQueue queue;
    InitializeQueue(&queue, num_processes);

    int time = 0;
    int remaining_processes = num_processes;

    while (remaining_processes > 0)
    {
        for (int i = 0; i < num_processes; ++i)
        {
            if (processes[i].arrival_time <= time && processes[i].remaining_time > 0)
            {
                // 进程可执行
                EnterQueue(&queue, &processes[i]);
            }
        }

        if (queue.size > 0)
        {
            Process *current_process = PollQueue(&queue);

            // 执行进程
            int execution_time = (current_process->remaining_time <= time_slice) ? current_process->remaining_time : time_slice;
            printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", current_process->name, current_process->arrival_time, current_process->burst_time,
                   time, time + execution_time, time + execution_time - current_process->arrival_time,
                   (float)(time + execution_time - current_process->arrival_time) / current_process->burst_time);

            // 更新进程信息
            current_process->remaining_time -= execution_time;
            time += execution_time;

            // 将未执行完的进程重新加入队列
            if (current_process->remaining_time > 0)
            {
                EnterQueue(&queue, current_process);
            }
            else
            {
                --remaining_processes;
            }
        }
        else
        {
            // 等待下一个进程到达
            time++;
        }
    }

    printf("轮转调度算法完成.\n");
}

int main()
{
    int num_processes = 3;
    int time_slice = 2;

    // 初始化进程数组
    Process processes[num_processes];
    strcpy(processes[0].name, "P1");
    processes[0].arrival_time = 0;
    processes[0].burst_time = 5;
    processes[0].remaining_time = processes[0].burst_time;

    strcpy(processes[1].name, "P2");
    processes[1].arrival_time = 1;
    processes[1].burst_time = 3;
    processes[1].remaining_time = processes[1].burst_time;

    strcpy(processes[2].name, "P3");
    processes[2].arrival_time = 3;
    processes[2].burst_time = 6;
    processes[2].remaining_time = processes[2].burst_time;

    // 调用轮转调度函数
    RoundRobin(processes, num_processes, time_slice);

    return 0;
}

 

 

操作系统进程调度算法有多,其中比较常见的有先来先服务(FCFS)、短作业优先(SJF)、时间片轮转(RR)、优先级调度等。下面是这些算法的简单介绍和C语言代码示例。 1. 先来先服务(FCFS) 先来先服务是一非抢占式的调度算法,按照进程到达的先后顺序分配CPU时间片。如果当前正在执行的进程没有完成,那么后续到达的进程就必须等待。这算法的优点是简单易实现,但如果有长时间的进程到来,则会导致后续进程长时间等待。 C语言代码示例: ```c #include<stdio.h> int main() { int n, bt[20], wt[20], tat[20], avwt=0, avtat=0, i, j; printf("Enter total number of processes(maximum 20):"); scanf("%d", &n); printf("\nEnter Process Burst Time\n"); for(i=0;i<n;i++) { printf("P[%d]:",i+1); scanf("%d",&bt[i]); } wt=0; //Waiting time for first process is 0 //Calculating waiting time for(i=1;i<n;i++) { wt[i]=0; for(j=0;j<i;j++) wt[i]+=bt[j]; } printf("\nProcess\t\tBurst Time\tWaiting Time\tTurnaround Time"); //Calculating turnaround time and average waiting time for(i=0;i<n;i++) { tat[i]=bt[i]+wt[i]; avwt+=wt[i]; avtat+=tat[i]; printf("\nP[%d]\t\t%d\t\t%d\t\t%d",i+1,bt[i],wt[i],tat[i]); } avwt/=i; avtat/=i; printf("\n\nAverage Waiting Time:%d",avwt); printf("\nAverage Turnaround Time:%d",avtat); return 0; } ``` 2. 短作业优先(SJF) 短作业优先是一非抢占式的调度算法,按照进程的执行时间长度来进行调度。当有多个进程的执行时间相同时,按照到达时间的先后顺序进行调度。这算法的优点是可以减少平均等待时间,但如果有长时间的进程到来,则会导致后续进程长时间等待。 C语言代码示例: ```c #include<stdio.h> int main() { int n, bt[20], wt[20], tat[20], avwt=0, avtat=0, i, j, pos, temp; printf("Enter total number of processes(maximum 20):"); scanf("%d", &n); printf("\nEnter Process Burst Time\n"); for(i=0;i<n;i++) { printf("P[%d]:",i+1); scanf("%d",&bt[i]); } //Sorting burst time in ascending order using selection sort for(i=0;i<n;i++) { pos=i; for(j=i+1;j<n;j++) { if(bt[j]<bt[pos]) pos=j; } temp=bt[i]; bt[i]=bt[pos]; bt[pos]=temp; } wt=0; //Waiting time for first process is 0 //Calculating waiting time for(i=1;i<n;i++) { wt[i]=0; for(j=0;j<i;j++) wt[i]+=bt[j]; } printf("\nProcess\t\tBurst Time\tWaiting Time\tTurnaround Time"); //Calculating turnaround time and average waiting time for(i=0;i<n;i++) { tat[i]=bt[i]+wt[i]; avwt+=wt[i]; avtat+=tat[i]; printf("\nP[%d]\t\t%d\t\t%d\t\t%d",i+1,bt[i],wt[i],tat[i]); } avwt/=i; avtat/=i; printf("\n\nAverage Waiting Time:%d",avwt); printf("\nAverage Turnaround Time:%d",avtat); return 0; } ``` 3. 时间片轮转(RR) 时间片轮转是一抢占式的调度算法,每个进程被分配一个时间片,当时间片用完时,该进程就会被挂起,并且把CPU分配给下一个进程。如果进程在时间片用完之前完成了任务,则它会被立即切换下一个进程。这算法适用于处理多个短进程。 C语言代码示例: ```c #include<stdio.h> int main() { int i, n, qt, count=0, time, remain, flag=0, wt=0, tat=0, at[20], bt[20], rt[20]; printf("Enter Total Process:\t "); scanf("%d",&n); remain=n; for(i=0;i<n;i++) { printf("Enter Arrival Time and Burst Time for Process Number %d :",i+1); scanf("%d",&at[i]); scanf("%d",&bt[i]); rt[i]=bt[i]; } printf("Enter Time Quantum:\t"); scanf("%d",&qt); printf("\n\nProcess\t|Turnaround Time|Waiting Time\n\n"); for(time=0,i=0;remain!=0;) { if(rt[i]<=qt && rt[i]>0) { time+=rt[i]; rt[i]=0; flag=1; } else if(rt[i]>0) { rt[i]-=qt; time+=qt; } if(rt[i]==0 && flag==1) { remain--; printf("P[%d]\t|\t%d\t|\t%d\n",i+1,time-at[i],time-at[i]-bt[i]); wt+=time-at[i]-bt[i]; tat+=time-at[i]; flag=0; } if(i==n-1) i=0; else if(at[i+1]<=time) i++; else i=0; } printf("\nAverage Waiting Time=%f\n",wt*1.0/n); printf("Average Turnaround Time=%f\n",tat*1.0/n); return 0; } ``` 4. 优先级调度 优先级调度是一非抢占式的调度算法,每个进程被分配一个优先级,按照优先级高低进行调度。如果有多个进程优先级相同,则按照到达时间的先后顺序进行调度。这算法的缺点是可能导致低优先级的进程长时间等待。 C语言代码示例: ```c #include<stdio.h> int main() { int n, bt[20], wt[20], tat[20], p[20], i, j, pos, temp; float avwt=0, avtat=0; printf("Enter total number of processes(maximum 20):"); scanf("%d", &n); printf("\nEnter Burst Time and Priority\n"); for(i=0;i<n;i++) { printf("\nP[%d]\n", i+1); printf("Burst Time:"); scanf("%d", &bt[i]); printf("Priority:"); scanf("%d", &p[i]); } //Sorting burst time and priority in ascending order using selection sort for(i=0;i<n;i++) { pos=i; for(j=i+1;j<n;j++) { if(p[j]<p[pos]) pos=j; } temp=p[i]; p[i]=p[pos]; p[pos]=temp; temp=bt[i]; bt[i]=bt[pos]; bt[pos]=temp; } wt=0; //waiting time for first process is zero //calculating waiting time for(i=1;i<n;i++) { wt[i]=0; for(j=0;j<i;j++) wt[i]+=bt[j]; avwt+=wt[i]; } avwt/=i; //average waiting time printf("\nProcess\t\tBurst Time\tWaiting Time\tTurnaround Time"); //calculating turnaround time and average turnaround time for(i=0;i<n;i++) { tat[i]=bt[i]+wt[i]; avtat+=tat[i]; printf("\nP[%d]\t\t%d\t\t%d\t\t%d", i+1, bt[i], wt[i], tat[i]); } avtat/=i; //average turnaround time printf("\n\nAverage Waiting Time=%f", avwt); printf("\nAverage Turnaround Time=%f", avtat); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值