69天探索操作系统-第38天:CPU 调度

## 1. 介绍 CPU调度是现代操作系统的关键组成部分,确保高效地分配资源和进行进程管理。它涉及复杂的算法,这些算法决定了进程执行的顺序,并平衡优先级、公平性和实时约束等因素。这些算法旨在优化CPU利用率,减少等待时间,并确保关键任务的及时执行。

高级CPU调度中的关键概念包括多级队列管理基于优先级的调度抢占机和负载平衡。多级队列允许进程被分类到不同的优先级级别,每个级别都有其自己的调度算法。基于优先级的调度确保高优先级任务首先执行,而实时调度则保证时间敏感任务能够满足其截止时间。这些技术对于构建迅速且高效的操作系统至关重要。

2.多级队列实现

2.1 多级队列调度

多级队列调度根据优先级或其他标准将进程划分为多个队列。每个队列可以有自己的调度算法,例如轮转调度或先到先服务(FCFS)。高优先级队列中的进程先于低优先级队列中的进程执行。这种方法通常用于操作系统,以处理交互式、批处理和实时进程的混合情况。

以下代码演示了一个多级队列的实现:

C 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAX_QUEUES 5
#define MAX_PROCESSES 100

typedef struct Process {
    int pid;
    int priority;
    int burst_time;
    int remaining_time;
    int arrival_time;
    int waiting_time;
    int turnaround_time;
} Process;

typedef struct Queue {
    Process *processes;
    int front;
    int rear;
    int size;
    int time_quantum;
    int priority_level;
} Queue;

typedef struct MultiLevelQueue {
    Queue queues[MAX_QUEUES];
    int num_queues;
} MultiLevelQueue;

void init_queue(Queue *q, int priority_level, int time_quantum) {
    q->processes = (Process*)malloc(MAX_PROCESSES * sizeof(Process));
    q->front = q->rear = -1;
    q->size = 0;
    q->priority_level = priority_level;
    q->time_quantum = time_quantum;
}

bool is_queue_empty(Queue *q) {
    return q->size == 0;
}

void enqueue(Queue *q, Process p) {
    if (q->size == MAX_PROCESSES) return;

    if (q->front == -1) {
        q->front = 0;
    }

    q->rear = (q->rear + 1) % MAX_PROCESSES;
    q->processes[q->rear] = p;
    q->size++;
}

Process dequeue(Queue *q) {
    Process p = q->processes[q->front];

    if (q->front == q->rear) {
        q->front = q->rear = -1;
    } else {
        q->front = (q->front + 1) % MAX_PROCESSES;
    }

    q->size--;
    return p;
}

MultiLevelQueue* init_multilevel_queue(int num_queues) {
    MultiLevelQueue *mlq = (MultiLevelQueue*)malloc(sizeof(MultiLevelQueue));
    mlq->num_queues = num_queues;

    for (int i = 0; i < num_queues; i++) {
        init_queue(&mlq->queues[i], i, (i + 1) * 2);
    }

    return mlq;
}

void schedule_processes(MultiLevelQueue *mlq) {
    int current_time = 0;
    bool all_queues_empty;

    do {
        all_queues_empty = true;

        for (int i = 0; i < mlq->num_queues; i++) {
            Queue *current_queue = &mlq->queues[i];

            if (!is_queue_empty(current_queue)) {
                all_queues_empty = false;
                Process current_process = dequeue(current_queue);

                int execution_time = (current_queue->time_quantum < current_process.remaining_time)
                                   ? current_queue->time_quantum
                                   : current_process.remaining_time;
                current_process.remaining_time -= execution_time;
                current_time += execution_time;

                if (current_process.remaining_time > 0) {
                    if (i < mlq->num_queues - 1) {
                        enqueue(&mlq->queues[i + 1], current_process);
                    } else {
                        enqueue(current_queue, current_process);
                    }
                } else {
                    current_process.turnaround_time = current_time - current_process.arrival_time;
                    current_process.waiting_time = current_process.turnaround_time - current_process.burst_time;

                    printf("Process %d completed. Turnaround Time: %d, Waiting Time: %d\n",
                           current_process.pid,
                           current_process.turnaround_time,
                           current_process.waiting_time);
                }
            }
        }
    } while (!all_queues_empty);
}

运行代码

shell 复制代码
gcc -o multilevel_queue multilevel_queue.c
./multilevel_queue

3. 基于优先级的调度

3.1 优先级调度算法

优先调度为每个进程分配一个优先级,优先级最高的进程先执行。该算法有助于确保关键任务得到及时处理。以下代码使用最小堆实现了一个基于优先级的调度器:

C 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct {
    int pid;
    int priority;
    int burst_time;
    int remaining_time;
    bool is_active;
} PriorityProcess;

typedef struct {
    PriorityProcess *processes;
    int capacity;
    int size;
} PriorityQueue;

PriorityQueue* init_priority_queue(int capacity) {
    PriorityQueue *pq = (PriorityQueue*)malloc(sizeof(PriorityQueue));
    pq->processes = (PriorityProcess*)malloc(capacity * sizeof(PriorityProcess));
    pq->capacity = capacity;
    pq->size = 0;
    return pq;
}

void heapify(PriorityQueue *pq, int idx) {
    int smallest = idx;
    int left = 2 * idx + 1;
    int right = 2 * idx + 2;

    if (left < pq->size &&
        pq->processes[left].priority < pq->processes[smallest].priority) {
        smallest = left;
    }

    if (right < pq->size &&
        pq->processes[right].priority < pq->processes[smallest].priority) {
        smallest = right;
    }

    if (smallest != idx) {
        PriorityProcess temp = pq->processes[idx];
        pq->processes[idx] = pq->processes[smallest];
        pq->processes[smallest] = temp;
        heapify(pq, smallest);
    }
}

void insert_process(PriorityQueue *pq, PriorityProcess process) {
    if (pq->size == pq->capacity) return;

    pq->processes[pq->size] = process;

    int current = pq->size;
    while (current > 0 &&
           pq->processes[(current - 1) / 2].priority >
           pq->processes[current].priority) {
        PriorityProcess temp = pq->processes[(current - 1) / 2];
        pq->processes[(current - 1) / 2] = pq->processes[current];
        pq->processes[current] = temp;
        current = (current - 1) / 2;
    }

    pq->size++;
}

PriorityProcess extract_min(PriorityQueue *pq) {
    if (pq->size <= 0) {
        PriorityProcess empty = {0, 0, 0, 0, false};
        return empty;
    }

    PriorityProcess root = pq->processes[0];
    pq->processes[0] = pq->processes[pq->size - 1];
    pq->size--;

    heapify(pq, 0);
    return root;
}

void priority_schedule(PriorityQueue *pq) {
    int current_time = 0;
    int completed = 0;

    while (completed < pq->size) {
        PriorityProcess current = extract_min(pq);

        if (current.is_active) {
            printf("Time %d: Executing process %d (Priority: %d)\n",
                   current_time, current.pid, current.priority);

            current.remaining_time--;
            current_time++;

            if (current.remaining_time > 0) {
                insert_process(pq, current);
            } else {
                completed++;
                printf("Process %d completed at time %d\n",
                       current.pid, current_time);
            }
        }
    }
}

运行代码:

shell 复制代码
gcc -o priority_scheduler priority_scheduler.c
./priority_scheduler

4. 实时调度

4.1 最早截止时间优先(EDF)调度

实时调度确保时间敏感任务能够按时完成。最早截止时间优先(EDF)算法首先调度截止时间最近的进程。以下代码展示了EDF调度:

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>

typedef struct {
    int pid;
    int period;
    int execution_time;
    int deadline;
    int next_deadline;
    bool is_periodic;
} RTProcess;

typedef struct {
    RTProcess *processes;
    int size;
    int capacity;
} RTScheduler;

RTScheduler* init_rt_scheduler(int capacity) {
    RTScheduler *rts = (RTScheduler*)malloc(sizeof(RTScheduler));
    rts->processes = (RTProcess*)malloc(capacity * sizeof(RTProcess));
    rts->capacity = capacity;
    rts->size = 0;
    return rts;
}

bool edf_schedule(RTScheduler *rts, int simulation_time) {
    int current_time = 0;

    while (current_time < simulation_time) {
        int earliest_deadline_idx = -1;
        int min_deadline = INT_MAX;

        for (int i = 0; i < rts->size; i++) {
            if (rts->processes[i].next_deadline < min_deadline &&
                rts->processes[i].execution_time > 0) {
                min_deadline = rts->processes[i].next_deadline;
                earliest_deadline_idx = i;
            }
        }

        if (earliest_deadline_idx != -1) {
            RTProcess *current = &rts->processes[earliest_deadline_idx];

            printf("Time %d: Executing process %d (Deadline: %d)\n",
                   current_time, current->pid, current->next_deadline);

            current->execution_time--;
            current_time++;

            if (current_time > current->next_deadline) {
                printf("Deadline missed for process %d\n", current->pid);
                return false;
            }

            if (current->execution_time == 0 && current->is_periodic) {
                current->execution_time = current->period;
                current->next_deadline += current->period;
            }
        } else {
            current_time++;
        }
    }

    return true;
}

运行代码:

shell 复制代码
gcc -o realtime_scheduler realtime_scheduler.c
./realtime_scheduler

5. 性能分析

性能分析涉及计算平均等待时间、周转时间、CPU 利用率和吞吐量等指标。以下代码演示了如何计算这些指标:

c 复制代码
typedef struct {
    double avg_waiting_time;
    double avg_turnaround_time;
    double cpu_utilization;
    double throughput;
    int context_switches;
} SchedulerMetrics;

SchedulerMetrics calculate_metrics(Process *processes, int n, int total_time) {
    SchedulerMetrics metrics = {0};
    int total_waiting_time = 0;
    int total_turnaround_time = 0;

    for (int i = 0; i < n; i++) {
        total_waiting_time += processes[i].waiting_time;
        total_turnaround_time += processes[i].turnaround_time;
    }

    metrics.avg_waiting_time = (double)total_waiting_time / n;
    metrics.avg_turnaround_time = (double)total_turnaround_time / n;
    metrics.cpu_utilization = ((double)total_time - metrics.avg_waiting_time) /
                             total_time * 100;
    metrics.throughput = (double)n / total_time;

    return metrics;
}

运行代码:

shell 复制代码
gcc -o scheduler_metrics scheduler_metrics.c
./scheduler_metrics

6. 总结

高级CPU调度对于优化现代操作系统的进程执行至关重要。通过理解和实施多级队列、基于优先级的调度和实时调度,开发人员可以构建高效且响应迅速的系统。提供的代码示例展示了这些概念的实际方法,使您能够分析和改进调度性能。

相关推荐
Victor35617 分钟前
MongoDB(2)MongoDB与传统关系型数据库的主要区别是什么?
后端
JaguarJack17 分钟前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端·php·服务端
BingoGo18 分钟前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端
Victor35619 分钟前
MongoDB(3)什么是文档(Document)?
后端
牛奔2 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
想用offer打牌7 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
KYGALYX9 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
爬山算法9 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端