69天探索操作系统-第39天:实时操作系统内部结构

34 阅读6分钟
pro12.webp

1.介绍

实时操作系统(RTOS) 是一种专门为处理需要精确时间和高可靠性的实时应用程序而设计的操作系统。与通用操作系统不同,RTOS确保确定性行为,这意味着它保证任务将在指定的时间框架内完成。这对于汽车系统、医疗设备和工业自动化等应用程序至关重要,因为延迟可能导致灾难性后果。

实时操作系统的关键特性

  • 确定性行为: RTOS确保系统调用和中断的响应时间可预测。例如,在汽车系统中,气囊的展开必须在撞击检测后的毫秒内完成。
  • 基于优先级的调度: 任务被分配优先级,调度器确保最高优先级的任务总是获得CPU时间。在医疗呼吸机中,空气压力监测必须优先于显示更新。
  • 最小中断延迟: 实时操作系统(RTOS)将中断发生与中断服务例程执行之间的时间间隔降至最低。在工业自动化中,必须立即处理紧急停止信号,以防止设备损坏。
  • 抢占式多任务处理: 高优先级任务可以立即中断低优先级任务,确保关键操作不会被延迟。

2.实时操作系统内核架构

实时操作系统内核是管理系统资源并为应用程序提供服务的核心组件。它由几个关键组件组成:

  • 调度器: 实现任务调度算法并维护任务状态。
  • 任务管理器: 处理任务创建、删除和状态转换。
  • 中断处理程序: 以最小延迟管理硬件和软件中断。
  • 定时器服务: 为任务和系统操作提供高分辨率定时服务。

image.png

任务控制块 (TCB) 实现

TCB 是一种数据结构,用于存储特定任务的信息。以下是 C 语言中 TCB 的基本实现:

typedef struct {
    uint32_t *stack_ptr;        // Current stack pointer
    uint32_t stack_size;        // Stack size
    uint8_t priority;           // Task priority
    TaskState_t state;          // Current task state
    void (*task_function)(void*); // Task function pointer
    void *task_parameters;      // Task parameters
    uint32_t time_slice;        // Time slice for round-robin
    char task_name[16];         // Task identifier
} TCB_t;
  • 栈指针:指向任务当前的栈位置。
  • 优先级:决定任务的执行优先级。
  • 任务函数:任务将执行的功能。
  • 任务参数:传递给任务函数的参数。
  • 时间片:在轮转调度方案中分配给任务的时间。

3. 任务管理和调度

实时操作系统(RTOS)中的任务管理涉及创建、调度和维护任务在其整个生命周期中的状态。任务可以处于以下状态之一:

  • 运行:当前在CPU上执行。
  • 就绪:准备执行但等待CPU。
  • 阻塞:等待事件或资源。
  • 暂停:暂时不活跃。
  • 终止:执行完成。

任务创建实现

以下是如何在实时操作系统(RTOS)中创建任务的示例:

typedef enum {
    TASK_RUNNING,
    TASK_READY,
    TASK_BLOCKED,
    TASK_SUSPENDED,
    TASK_TERMINATED
} TaskState_t;

TCB_t* create_task(void (*task_func)(void*),
                   void* parameters,
                   uint8_t priority,
                   uint32_t stack_size) {
    TCB_t* new_task = (TCB_t*)malloc(sizeof(TCB_t));
    if (new_task == NULL) return NULL;

    // Allocate stack
    new_task->stack_ptr = malloc(stack_size);
    if (new_task->stack_ptr == NULL) {
        free(new_task);
        return NULL;
    }

    // Initialize TCB
    new_task->stack_size = stack_size;
    new_task->priority = priority;
    new_task->state = TASK_READY;
    new_task->task_function = task_func;
    new_task->task_parameters = parameters;
    new_task->time_slice = DEFAULT_TIME_SLICE;

    // Initialize stack frame
    initialize_stack_frame(new_task);

    return new_task;
}

4. 实时操作系统中的中断处理

中断处理对于实时系统至关重要。实时操作系统(RTOS)必须在保持确定性行为的同时高效地管理中断。以下是基本中断处理器的实现:

typedef struct {
    void (*isr)(void);
    uint8_t priority;
} ISR_Entry_t;

#define MAX_INTERRUPTS 256
ISR_Entry_t isr_table[MAX_INTERRUPTS];

void register_interrupt(uint8_t vector, void (*isr)(void), uint8_t priority) {
    if (vector < MAX_INTERRUPTS) {
        __disable_interrupts();
        isr_table[vector].isr = isr;
        isr_table[vector].priority = priority;
        __enable_interrupts();
    }
}

void interrupt_handler(uint8_t vector) {
    if (vector < MAX_INTERRUPTS && isr_table[vector].isr != NULL) {
        isr_table[vector].isr();
    }
}
  1. 中断注册:register_interrupt() 函数为特定中断向量注册一个中断服务例程(ISR)。
  2. 中断处理:当发生中断时,interrupt_handler() 函数执行中断服务例程(ISR)。

5. 计时管理

实时操作系统(RTOS)的定时器管理为任务和系统操作提供精确的定时服务。以下是基本定时器的实现:

typedef struct {
    uint32_t interval;
    uint32_t remaining;
    bool periodic;
    void (*callback)(void*);
    void* callback_param;
} Timer_t;

#define MAX_TIMERS 32
Timer_t timer_pool[MAX_TIMERS];

Timer_t* create_timer(uint32_t interval,
                     bool periodic,
                     void (*callback)(void*),
                     void* param) {
    Timer_t* timer = NULL;

    for (int i = 0; i < MAX_TIMERS; i++) {
        if (timer_pool[i].callback == NULL) {
            timer = &timer_pool[i];
            timer->interval = interval;
            timer->remaining = interval;
            timer->periodic = periodic;
            timer->callback = callback;
            timer->callback_param = param;
            break;
        }
    }

    return timer;
}

6. 任务间通信

实时操作系统(RTOS)为任务提供了通信和同步的机制。以下是消息队列的实现:

typedef struct {
    void* buffer;
    size_t msg_size;
    size_t queue_length;
    size_t count;
    size_t head;
    size_t tail;
} MessageQueue_t;

MessageQueue_t* create_queue(size_t msg_size, size_t length) {
    MessageQueue_t* queue = malloc(sizeof(MessageQueue_t));
    if (queue == NULL) return NULL;

    queue->buffer = malloc(msg_size * length);
    if (queue->buffer == NULL) {
        free(queue);
        return NULL;
    }

    queue->msg_size = msg_size;
    queue->queue_length = length;
    queue->count = 0;
    queue->head = 0;
    queue->tail = 0;

    return queue;
}

7. 实时操作系统中的内存管理

实时操作系统(RTOS)的内存管理侧重于确定性的分配和释放。以下是内存池的实现:

typedef struct {
    void* pool;
    size_t block_size;
    size_t num_blocks;
    uint8_t* block_status;
} MemoryPool_t;

MemoryPool_t* create_memory_pool(size_t block_size, size_t num_blocks) {
    MemoryPool_t* pool = malloc(sizeof(MemoryPool_t));
    if (pool == NULL) return NULL;

    pool->pool = malloc(block_size * num_blocks);
    if (pool->pool == NULL) {
        free(pool);
        return NULL;
    }

    pool->block_status = calloc(num_blocks, sizeof(uint8_t));
    if (pool->block_status == NULL) {
        free(pool->pool);
        free(pool);
        return NULL;
    }

    pool->block_size = block_size;
    pool->num_blocks = num_blocks;

    return pool;
}

8. 性能考虑

实时操作系统性能的关键指标包括:

  • 上下文切换时间: 在任务切换期间保存和恢复任务上下文所需的时间。对于嵌入式系统,通常小于1微秒。
  • 中断延迟: 中断发生与ISR执行之间的延迟。应可预测且最小,通常小于100纳秒。
  • 任务切换时间: 在任务之间切换的总时间,包括上下文切换和调度开销。应保持一致,通常在5微秒以下。
  • 内存占用: 实时操作系统内核的大小应尽可能小,通常为10-100KB,具体取决于所包含的功能。

9. 总结

实时操作系统(RTOS)的内部机制构成了可靠实时系统的基础。理解这些概念对于开发确定性和可靠的嵌入式系统至关重要。所涵盖的关键方面——任务管理、中断处理、定时服务和内存管理——共同作用,提供实时应用程序所需的可预测行为。