4. 实现AUTOSAR OS与QNX Neutrino的适配层

任务说明

本案例目标是在QNX Neutrino实时操作系统上实现一个AUTOSAR OS适配层,将AUTOSAR OS规范中的调度与中断管理接口映射到QNX的原生机制:调度使用pthread线程与优先级策略,中断使用QNX的信号(POSIX signal)与中断处理线程。适配层提供AUTOSAR风格的API,使上层OSEK/AUTOSAR应用代码无需修改即可在QNX上编译运行。

环境依赖

  • QNX SDP 7.0或更高版本(含qcc编译器)
  • 仅依赖POSIX pthread与signal,无额外第三方库

适配层设计

适配层核心包含三部分:任务管理(创建/终止/调度)、资源锁(优先级天花板协议模拟)、中断处理(信号映射)。AUTOSAR OS的TaskType映射为pthread句柄,ActivateTask对应创建或唤醒线程,TerminateTask对应线程退出。中断通过QNX的Signal机制绑定到专用处理线程,实现类似AUTOSAR的ISR分类。

关键完整代码

// os_adaptor.h
#ifndef OS_ADAPTOR_H
#define OS_ADAPTOR_H

#include <pthread.h>
#include <signal.h>
#include <stdint.h>

typedef enum { TASK_RUNNING, TASK_READY, TASK_SUSPENDED } TaskState;
typedef void (*TaskFunc)(void);
typedef void (*ISRFunc)(void);

typedef struct {
    pthread_t thread;
    TaskFunc entry;
    uint32_t priority;      // AUTOSAR优先级(1-255, 数值越小优先级越高)
    TaskState state;
    int activated;          // 激活计数
    pthread_mutex_t lock;
    pthread_cond_t cond;
} OsTask;

typedef struct {
    int sig_no;
    ISRFunc handler;
    pthread_t isr_thread;
    volatile int pending;
} OsIsr;

// 任务管理接口
void Os_Init(void);
int  Os_CreateTask(OsTask *task, TaskFunc entry, uint32_t priority);
int  Os_ActivateTask(OsTask *task);
int  Os_TerminateTask(OsTask *task);
void Os_Schedule(void);

// 中断接口
int  Os_InstallISR(OsIsr *isr, int sig_no, ISRFunc handler);
void Os_EnableISR(OsIsr *isr);
void Os_DisableISR(OsIsr *isr);

#endif // OS_ADAPTOR_H
// os_adaptor.c
#include "os_adaptor.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

static void *task_wrapper(void *arg) {
    OsTask *t = (OsTask*)arg;
    pthread_mutex_lock(&t->lock);
    while (1) {
        while (t->activated == 0) {
            t->state = TASK_SUSPENDED;
            pthread_cond_wait(&t->cond, &t->lock);
        }
        t->activated--;
        t->state = TASK_RUNNING;
        pthread_mutex_unlock(&t->lock);
        
        t->entry();  // 执行任务函数
        
        pthread_mutex_lock(&t->lock);
        t->state = TASK_SUSPENDED;
        pthread_mutex_unlock(&t->lock);
    }
    return NULL;
}

void Os_Init(void) {
    // 初始化全局状态(当前无全局资源)
}

int Os_CreateTask(OsTask *task, TaskFunc entry, uint32_t priority) {
    if (!task || !entry) return -1;
    task->entry = entry;
    task->priority = priority;
    task->activated = 0;
    task->state = TASK_SUSPENDED;
    pthread_mutex_init(&task->lock, NULL);
    pthread_cond_init(&task->cond, NULL);
    
    pthread_attr_t attr;
    struct sched_param param;
    pthread_attr_init(&attr);
    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    pthread_attr_setschedpolicy(&attr, SCHED_RR);
    param.sched_priority = 30 - (priority % 30); // QNX优先级范围1-30,映射
    pthread_attr_setschedparam(&attr, &param);
    
    int rc = pthread_create(&task->thread, &attr, task_wrapper, task);
    pthread_attr_destroy(&attr);
    return rc;
}

int Os_ActivateTask(OsTask *task) {
    if (!task) return -1;
    pthread_mutex_lock(&task->lock);
    task->activated++;
    task->state = TASK_READY;
    pthread_cond_signal(&task->cond);
    pthread_mutex_unlock(&task->lock);
    return 0;
}

int Os_TerminateTask(OsTask *task) {
    if (!task) return -1;
    pthread_cancel(task->thread);
    return 0;
}

void Os_Schedule(void) {
    sched_yield();  // 让出CPU,触发QNX调度
}

// ---- 中断处理 ----
static void sig_handler_wrapper(int sig) {
    // 信号处理函数(在进程上下文执行)
    // 实际处理由专用线程完成,这里仅置标志
    // 查找对应的ISR实例(简化:使用全局查找)
    extern OsIsr *g_isr_table[32];
    if (sig < 32 && g_isr_table[sig]) {
        g_isr_table[sig]->pending = 1;
        // 唤醒ISR线程
        pthread_kill(g_isr_table[sig]->isr_thread, SIGUSR1);
    }
}

static void *isr_thread_func(void *arg) {
    OsIsr *isr = (OsIsr*)arg;
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGUSR1);
    int sig;
    while (1) {
        sigwait(&set, &sig);  // 等待信号
        if (isr->pending) {
            isr->pending = 0;
            isr->handler();   // 调用AUTOSAR ISR处理函数
        }
    }
    return NULL;
}

OsIsr *g_isr_table[32] = {0};

int Os_InstallISR(OsIsr *isr, int sig_no, ISRFunc handler) {
    if (!isr || sig_no < 1 || sig_no > 31) return -1;
    isr->sig_no = sig_no;
    isr->handler = handler;
    isr->pending = 0;
    
    // 注册信号处理
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = sig_handler_wrapper;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(sig_no, &sa, NULL);
    
    // 创建ISR处理线程
    pthread_create(&isr->isr_thread, NULL, isr_thread_func, isr);
    g_isr_table[sig_no] = isr;
    return 0;
}

void Os_EnableISR(OsIsr *isr) {
    sigprocmask(SIG_UNBLOCK, &(sigset_t){isr->sig_no}, NULL);
}

void Os_DisableISR(OsIsr *isr) {
    sigprocmask(SIG_BLOCK, &(sigset_t){isr->sig_no}, NULL);
}
// main.c 验证示例
#include "os_adaptor.h"
#include <stdio.h>
#include <unistd.h>

static OsTask task1, task2;
static OsIsr isr1;

void Task1_Entry(void) {
    for (int i = 0; i < 3; i++) {
        printf("[Task1] 执行第%d次\n", i+1);
        Os_Schedule();
        usleep(100000);
    }
    printf("[Task1] 完成\n");
}

void Task2_Entry(void) {
    for (int i = 0; i < 2; i++) {
        printf("[Task2] 执行第%d次\n", i+1);
        Os_Schedule();
        usleep(150000);
    }
    printf("[Task2] 完成\n");
}

void ISR1_Handler(void) {
    printf("[ISR1] 中断处理触发\n");
}

int main(void) {
    Os_Init();
    
    // 创建两个任务
    Os_CreateTask(&task1, Task1_Entry, 5);   // 高优先级
    Os_CreateTask(&task2, Task2_Entry, 10);  // 低优先级
    
    // 安装中断 (使用SIGRTMIN+1)
    Os_InstallISR(&isr1, SIGRTMIN+1, ISR1_Handler);
    Os_EnableISR(&isr1);
    
    // 激活任务
    Os_ActivateTask(&task1);
    Os_ActivateTask(&task2);
    
    // 模拟外部中断触发
    sleep(1);
    printf("[main] 触发软件中断\n");
    raise(SIGRTMIN+1);
    
    sleep(2);
    printf("[main] 测试结束\n");
    return 0;
}

编译与运行

qcc -o os_adaptor_test main.c os_adaptor.c -l pthread
./os_adaptor_test

验证方法与通过标准

运行程序后,观察输出应满足以下条件即判定适配层工作正常:

  • 任务调度验证:Task1(优先级5)先于Task2(优先级10)执行,且Task1的3次执行与Task2的2次执行交替出现(因Os_Schedule主动让出CPU);
  • 中断映射验证:main函数中raise(SIGRTMIN+1)触发后,ISR1_Handler被调用,输出[ISR1] 中断处理触发;
  • 任务生命周期:两个任务均打印“完成”字样,表明任务函数正常执行完毕并返回。

若输出顺序符合上述描述且无崩溃或死锁,则适配层实现正确。注意:实际调度顺序可能因QNX系统负载略有差异,但Task1先于Task2启动且两者均完成即为通过。