202603171903_《实时OS Kernel》
状态:
-
未创建态
-
就绪态 (Ready)
-
运行态 (Running)
-
延时态 (Blocked/Delayed)
-
挂起态 (Suspended)
-
事件 (Event waiting)
关键转换:
-
a: 创建 → 就绪
-
b: 就绪 → 运行 (优先级最高)
-
c: 运行 → 就绪 (被抢占)
-
d: 运行 → 事件 (等待事件)
-
e: 事件 → 运行
-
f: 延时态 → 就绪 (延时结束)
-
g: 就绪 → 延时态
-
h: 运行 → 延时态 (延时)
-
i: 就绪 → 挂起态 (挂起)
-
j: 运行 → 挂起态 (挂起)
-
k: 挂起态 → 就绪 (恢复,优先级低)
-
m: 挂起态 → 运行 (恢复,优先级高)
这个实现内容比较多,为了确保核心逻辑清晰,我分成两个文件来写:
一个头文件定义核心结构(mini_rtos.h)
一个 C 文件实现调度器(mini_rtos.c)
/*-- mini_rtos.h --*/ #ifndef MINI_RTOS_H #define MINI_RTOS_H #include <stdint.h> #include <stdbool.h> #include <string.h> #include <stdio.h> #include <stdlib.h> /* ---- 配置 ---- */ #define MAX_TASKS 8 #define MAX_PRIORITY 4 #define STACK_SIZE 256 /* ---- 任务状态(对应流程图中的 5 个状态) ---- */ typedef enum { TASK_STATE_NONE = 0, /* 未创建态 */ TASK_STATE_READY, /* 就绪态 */ TASK_STATE_RUNNING, /* 运行态 */ TASK_STATE_BLOCKED, /* 延时态 / 事件等待态 */ TASK_STATE_SUSPENDED /* 挂起态 */ } TaskState_t; /* ---- 事件类型 ---- */ typedef enum { EVENT_NONE = 0, EVENT_DELAY, /* 纯延时阻塞 */ EVENT_SEMAPHORE /* 信号量等待 */ } BlockReason_t; /* ---- 任务控制块 TCB ---- */ typedef struct TCB { uint8_t id; char name[16]; TaskState_t state; uint8_t priority; /* 数值越大优先级越高 */ void (*taskFunc)(void *); void *param; /* 阻塞/延时相关 */ BlockReason_t blockReason; uint32_t delayTicks; /* 剩余延时 tick 数 */ uint32_t timeoutTicks; /* 事件等待超时 (0=永久) */ } TCB_t; /* ---- 简易信号量 ---- */ typedef struct { volatile int count; int waitingTaskId; /* 简化:只允许一个任务等待 */ } Semaphore_t; /* ---- API 声明 ---- */ /* 调度器 */ void OS_Init(void); int OS_CreateTask(void (*func)(void *), void *param, uint8_t priority, const char *name); void OS_StartScheduler(void); void OS_Schedule(void); /* 状态转换 (对应流程图箭头) */ void OS_Delay(uint32_t ticks); /* h: 运行→延时 */ void OS_Suspend(int taskId); /* i/j: 就绪/运行→挂起 */ void OS_Resume(int taskId); /* k/m: 挂起→就绪/运行 */ /* 信号量 */ void OS_SemInit(Semaphore_t *sem, int initVal); bool OS_SemWait(Semaphore_t *sem, uint32_t timeout); /* d: 运行→事件 */ void OS_SemPost(Semaphore_t *sem); /* e: 事件→就绪/运行 */ /* Tick 心跳 */ void OS_Tick(void); /* 调试 */ void OS_PrintState(void); #endif /* MINI_RTOS_H */
/*-- mini_rtos.c --*/ #include "mini_rtos.h" /* ---- 全局变量 ---- */ static TCB_t taskPool[MAX_TASKS]; static int taskCount = 0; static int currentTask = -1; /* 当前运行态任务 ID */ static uint32_t tickCount = 0; /* ================================================================ * 辅助:选出优先级最高的就绪态任务 * ================================================================ */ static int findHighestReadyTask(void) { int best = -1; uint8_t bestPri = 0; for (int i = 0; i < taskCount; i++) { if (taskPool[i].state == TASK_STATE_READY) { if (best == -1 || taskPool[i].priority > bestPri) { best = i; bestPri = taskPool[i].priority; } } } return best; } /* ================================================================ * a: 未创建态 → 就绪态 (OS_CreateTask) * ================================================================ */ void OS_Init(void) { memset(taskPool, 0, sizeof(taskPool)); taskCount = 0; currentTask = -1; tickCount = 0; printf("[OS] 内核初始化完成\n"); } int OS_CreateTask(void (*func)(void *), void *param, uint8_t priority, const char *name) { if (taskCount >= MAX_TASKS) { printf("[OS] 任务池已满!\n"); return -1; } int id = taskCount++; TCB_t *t = &taskPool[id]; t->id = id; t->taskFunc = func; t->param = param; t->priority = priority; t->state = TASK_STATE_READY; /* 转换 a */ t->blockReason = EVENT_NONE; t->delayTicks = 0; t->timeoutTicks = 0; strncpy(t->name, name, sizeof(t->name) - 1); printf("[OS] 创建任务 \"%s\" (id=%d, pri=%d) 未创建→就绪 [转换a]\n", name, id, priority); return id; } /* ================================================================ * b: 就绪→运行 / c: 运行→就绪(被抢占) —— 核心调度 * ================================================================ */ void OS_Schedule(void) { int next = findHighestReadyTask(); /* 没有就绪任务 */ if (next == -1) { if (currentTask >= 0 && taskPool[currentTask].state == TASK_STATE_RUNNING) { /* 当前任务继续运行 */ return; } printf("[OS] 无就绪任务,IDLE\n"); currentTask = -1; return; } /* 当前任务仍在运行且优先级 >= next → 不切换 */ if (currentTask >= 0 && taskPool[currentTask].state == TASK_STATE_RUNNING && taskPool[currentTask].priority >= taskPool[next].priority) { return; } /* 抢占:当前运行→就绪 (转换 c) */ if (currentTask >= 0 && taskPool[currentTask].state == TASK_STATE_RUNNING) { taskPool[currentTask].state = TASK_STATE_READY; printf("[OS] 任务 \"%s\" 运行→就绪 (被抢占) [转换c]\n", taskPool[currentTask].name); } /* 切入新任务:就绪→运行 (转换 b) */ taskPool[next].state = TASK_STATE_RUNNING; currentTask = next; printf("[OS] 任务 \"%s\" 就绪→运行 (优先级最高) [转换b]\n", taskPool[next].name); } /* ================================================================ * h: 运行→延时态 (OS_Delay) * g: 就绪→延时态 (内部也支持) * ================================================================ */ void OS_Delay(uint32_t ticks) { if (currentTask < 0) return; TCB_t *t = &taskPool[currentTask]; t->state = TASK_STATE_BLOCKED; /* 转换 h */ t->blockReason = EVENT_DELAY; t->delayTicks = ticks; printf("[OS] 任务 \"%s\" 运行→延时态 (delay=%u ticks) [转换h]\n", t->name, ticks); OS_Schedule(); /* 立即重新调度 */ } /* ================================================================ * d: 运行→事件等待 (OS_SemWait) * f: 延时/事件→就绪 (超时或获取成功) * ================================================================ */ void OS_SemInit(Semaphore_t *sem, int initVal) { sem->count = initVal; sem->waitingTaskId = -1; } bool OS_SemWait(Semaphore_t *sem, uint32_t timeout) { if (sem->count > 0) { sem->count--; printf("[OS] 任务 \"%s\" 获取信号量成功 (剩余=%d)\n", taskPool[currentTask].name, sem->count); return true; } /* 信号量不可用 → 阻塞 (转换 d) */ TCB_t *t = &taskPool[currentTask]; t->state = TASK_STATE_BLOCKED; t->blockReason = EVENT_SEMAPHORE; t->timeoutTicks = timeout; /* 0 = 永久等待 */ sem->waitingTaskId = currentTask; printf("[OS] 任务 \"%s\" 运行→事件等待 (sem, timeout=%u) [转换d]\n", t->name, timeout); OS_Schedule(); /* 模拟返回后检查是否超时 */ if (t->blockReason == EVENT_NONE) { return true; /* 被 SemPost 唤醒 */ } return false; /* 超时 */ } /* e: 事件→就绪/运行 */ void OS_SemPost(Semaphore_t *sem) { sem->count++; if (sem->waitingTaskId >= 0) { TCB_t *t = &taskPool[sem->waitingTaskId]; if (t->state == TASK_STATE_BLOCKED && t->blockReason == EVENT_SEMAPHORE) { t->state = TASK_STATE_READY; /* 转换 e→就绪 */ t->blockReason = EVENT_NONE; printf("[OS] 任务 \"%s\" 事件等待→就绪 (信号量释放) [转换e]\n", t->name); sem->waitingTaskId = -1; sem->count--; /* 直接分配给等待者 */ OS_Schedule(); /* 可能触发抢占 */ } } } /* ================================================================ * i: 就绪→挂起 / j: 运行→挂起 (OS_Suspend) * ================================================================ */ void OS_Suspend(int taskId) { if (taskId < 0 || taskId >= taskCount) return; TCB_t *t = &taskPool[taskId]; const char *from = (t->state == TASK_STATE_RUNNING) ? "运行" : "就绪"; const char *tr = (t->state == TASK_STATE_RUNNING) ? "j" : "i"; t->state = TASK_STATE_SUSPENDED; /* 转换 i 或 j */ printf("[OS] 任务 \"%s\" %s→挂起 [转换%s]\n", t->name, from, tr); if (taskId == currentTask) { currentTask = -1; OS_Schedule(); } } /* ================================================================ * k: 挂起→就绪 (恢复,优先级低) * m: 挂起→运行 (恢复,优先级高) * ================================================================ */ void OS_Resume(int taskId) { if (taskId < 0 || taskId >= taskCount) return; TCB_t *t = &taskPool[taskId]; if (t->state != TASK_STATE_SUSPENDED) return; /* 先设为就绪 */ t->state = TASK_STATE_READY; /* 判断是否比当前运行任务优先级高 → 直接切换运行 (转换 m) */ if (currentTask < 0 || t->priority > taskPool[currentTask].priority) { printf("[OS] 任务 \"%s\" 挂起→运行 (恢复,优先级高) [转换m]\n", t->name); OS_Schedule(); } else { printf("[OS] 任务 \"%s\" 挂起→就绪 (恢复,优先级低) [转换k]\n", t->name); } } /* ================================================================ * Tick 心跳 —— 处理延时到期 (转换 f) 和事件超时 * ================================================================ */ void OS_Tick(void) { tickCount++; bool needSchedule = false; for (int i = 0; i < taskCount; i++) { TCB_t *t = &taskPool[i]; if (t->state != TASK_STATE_BLOCKED) continue; /* 延时阻塞 → tick 递减 */ if (t->blockReason == EVENT_DELAY) { if (t->delayTicks > 0) t->delayTicks--; if (t->delayTicks == 0) { t->state = TASK_STATE_READY; /* 转换 f */ t->blockReason = EVENT_NONE; printf("[OS] tick=%u: 任务 \"%s\" 延时结束→就绪 [转换f]\n", tickCount, t->name); needSchedule = true; } } /* 事件等待超时 */ if (t->blockReason == EVENT_SEMAPHORE && t->timeoutTicks > 0) { t->timeoutTicks--; if (t->timeoutTicks == 0) { t->state = TASK_STATE_READY; /* 超时→就绪 */ t->blockReason = EVENT_NONE; printf("[OS] tick=%u: 任务 \"%s\" 事件超时→就绪 [转换f]\n", tickCount, t->name); needSchedule = true; } } } if (needSchedule) { OS_Schedule(); } } /* ================================================================ * 启动调度器 * ================================================================ */ void OS_StartScheduler(void) { printf("[OS] ===== 调度器启动 =====\n"); OS_Schedule(); } /* ================================================================ * 调试打印 * ================================================================ */ static const char *stateStr(TaskState_t s) { switch (s) { case TASK_STATE_NONE: return "未创建"; case TASK_STATE_READY: return "就绪"; case TASK_STATE_RUNNING: return "运行"; case TASK_STATE_BLOCKED: return "阻塞"; case TASK_STATE_SUSPENDED: return "挂起"; default: return "???"; } } void OS_PrintState(void) { printf("\n--- 任务状态快照 (tick=%u) ---\n", tickCount); for (int i = 0; i < taskCount; i++) { printf(" [%d] %-10s pri=%d state=%s", i, taskPool[i].name, taskPool[i].priority, stateStr(taskPool[i].state)); if (taskPool[i].state == TASK_STATE_BLOCKED) { if (taskPool[i].blockReason == EVENT_DELAY) printf(" (delay剩余=%u)", taskPool[i].delayTicks); else if (taskPool[i].blockReason == EVENT_SEMAPHORE) printf(" (等待信号量, timeout=%u)", taskPool[i].timeoutTicks); } printf("\n"); } printf("----------------------------\n\n"); }
/*-- main.c --*/ #include "mini_rtos.h" /* 空的任务函数(实际调度由我们手动驱动) */ void taskA_func(void *p) { (void)p; } void taskB_func(void *p) { (void)p; } void taskC_func(void *p) { (void)p; } int main(void) { OS_Init(); /* a: 未创建→就绪 */ int idA = OS_CreateTask(taskA_func, NULL, 3, "TaskA"); int idB = OS_CreateTask(taskB_func, NULL, 2, "TaskB"); int idC = OS_CreateTask(taskC_func, NULL, 1, "TaskC"); /* b: 就绪→运行 (TaskA 优先级最高) */ OS_StartScheduler(); OS_PrintState(); /* h: TaskA 运行→延时态 (delay 3 ticks) */ OS_Delay(3); OS_PrintState(); /* 此时 TaskB 应该被调度运行 (转换 b) */ /* j: TaskB 运行→挂起 */ OS_Suspend(idB); OS_PrintState(); /* TaskC 被调度运行 */ /* i: TaskC 运行时,把自己挂起 */ OS_Suspend(idC); OS_PrintState(); /* k: 恢复 TaskB (优先级低于... 无人运行,直接运行) */ OS_Resume(idB); OS_PrintState(); /* 模拟 tick 心跳,让 TaskA 延时到期 */ printf("=== 模拟 3 次 tick ===\n"); OS_Tick(); /* tick 1 */ OS_Tick(); /* tick 2 */ OS_Tick(); /* tick 3 → TaskA 延时结束, f: 延时→就绪, 抢占 TaskB */ OS_PrintState(); /* d/e: 信号量演示 */ printf("=== 信号量演示 ===\n"); Semaphore_t sem; OS_SemInit(&sem, 0); /* TaskA 正在运行,尝试等待信号量 → d: 运行→事件等待 */ OS_SemWait(&sem, 5); OS_PrintState(); /* 外部释放信号量 → e: 事件→就绪/运行 */ OS_SemPost(&sem); OS_PrintState(); /* m: 恢复 TaskC (优先级低) → 挂起→就绪 */ OS_Resume(idC); OS_PrintState(); printf("[OS] ===== 演示结束 =====\n"); return 0; }
前端-语言

浙公网安备 33010602011771号