202603171903_《实时OS Kernel》

状态:

  1. 未创建态

  2. 就绪态 (Ready)

  3. 运行态 (Running)

  4. 延时态 (Blocked/Delayed)

  5. 挂起态 (Suspended)

  6. 事件 (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;
}

 

 

posted @ 2026-03-17 19:07  Coca-code  阅读(11)  评论(0)    收藏  举报