# QNX Neutrino RTOS 系统架构
第一部分:QNX OS 设计哲学
1.1 概述
QNX OS 的首要目标是"以健壮、可扩展的形式交付开放系统的 POSIX API,适用于从微小嵌入式设备到分布式计算环境的广泛系统"。支持 x86 和 ARM 处理器家族。
1.2 可嵌入的 POSIX OS?
"根据一个流行神话,如果刨开一个 POSIX 操作系统,你会发现 UNIX 在表面之下!“但 POSIX 不是 UNIX。POSIX 标准以接口定义,而非实现。QNX OS 拥有"绝非 UNIX"的架构,通过微内核方法"以一种易于为实时嵌入式系统缩小或增量扩展的形式交付 POSIX API”。
1.3 产品扩展
由于微内核 OS 可以通过选择包含哪些进程来轻松扩展,“你可以将单个微内核 OS 用于比实时执行程序更广泛的目的”。产品线开发中,不同型号可以共享同一个微内核 OS —— “按需添加文件系统、网络、图形用户界面和其他技术”。
可扩展方法的优势:
- 产品线成员间可移植应用代码
- 整个产品线使用通用工具
- 开发人员可移植的技能集
- 缩短上市时间
1.4 为什么嵌入式系统选择 POSIX
| 标准 | 描述 |
|---|---|
| 1003.1 | 进程管理、设备 I/O、文件系统 I/O、基本 IPC |
| Realtime Extensions | 信号量、优先调度、实时信号、高精度定时器、增强 IPC、同步/异步 I/O |
| Threads | 单地址空间中的多线程创建和管理 |
| AEPs | 实时和嵌入式系统的应用环境配置文件 |
POSIX 的优势:
- 多 OS 来源 — 硬件制造商不依赖单一供应商
- 开发人员可移植性 — 经验可跨 RTOS 转移
- 开发环境 — 跨主机和目标系统 API 相同
1.5 为什么嵌入式系统选择 QNX OS
OS 的首要职责是"管理计算机的资源"。QNX OS “非常适合 嵌入式实时应用”,提供:
- 可扩展到非常小的占用空间
- 多任务和线程
- 优先级驱动的抢占式调度
- 快速上下文切换
所有功能都"带有 POSIX 标准 API",开发人员无需为小系统放弃标准。
两个基本原则:
- 微内核架构
- 基于消息的进程间通信
1.6 微内核架构
“微内核结构为"一个提供最小服务的微小内核,由一组可选的协作进程团队使用”。
关键设计目标:“模块化是关键,大小只是副作用。”
三种架构比较:
| 架构 | 内存保护 |
|---|---|
| 传统执行程序 | “无内存保护” |
| 宏内核 OS | “系统进程无保护” |
| 微内核 OS | “提供完整内存保护” |
QNX OS “充分利用 MMU 在受保护环境中交付完整的 POSIX 进程模型”。完整的 QNX OS 第一版于 1981 年发布。
1.7 IPC 的哲学角色
当线程在实时多任务环境中并发运行时,OS 必须提供通信机制。IPC 是"将应用设计为一组协作进程的关键",每个进程处理一个定义良好的部分。
第二部分:QNX OS 微内核
2.1 概述
"微内核实现了嵌入式实时系统中使用的核心 POSIX 特性,以及 QNX OS 基础的消息传递服务。"后续 QNX 微内核不断减少实现给定内核调用所需的代码。
微内核并非用汇编编写。实现主要用 C 语言编写;性能和大小通过不断改进的算法和数据结构实现,而非汇编级窥孔优化。
2.2 设计目标
微内核面临"来自计算领域两端"的压力——从内存受限的嵌入式系统到高端 SMP 机器。
核心目标:
- 跨越计算谱系的两端
- 容纳看似互斥的功能集
- 将系统范围扩展到其他 OS 实现无法达到的领域
- POSIX 实时和线程服务直接在微内核中实现
- 支持 POSIX 配置文件所需的纯线程模型
- 实现完整 POSIX 合规——需要带内存保护的进程模型
2.3 系统服务
微内核提供支持以下特性的内核调用:
- 线程
- 消息传递
- 信号
- 时钟
- 定时器
- 中断处理
- 信号量
- 互斥锁 (mutexes)
- 条件变量 (condvars)
- 屏障 (barriers)
关键特性:
- “整个 OS 完全可抢占,即使在进程间传递消息时也是如此”
- 最小复杂性的微内核有助于设置最长不可抢占代码路径的上限
- “中断被禁用或抢占被保持的间隔非常短暂(通常为几百纳秒量级)”
- 选择包含的服务基于"具有短执行路径"
- 需要显著工作量(如进程加载)的操作被放在外部进程/线程中
2.4 线程与进程
线程是微内核中调度和执行的最小单位。进程是线程的容器,定义了线程执行的地址空间。
线程与进程关系:
| 概念 | 描述 |
|---|---|
| Thread | 最小执行单位、调度和执行单位 |
| Process | 线程的容器,定义地址空间。始终包含至少一个线程 |
| pthread 调用 | 高级 API,有对应的微内核调用 |
| 进程模型 | 每个进程受 MMU 保护,可包含多个线程 |
pthread 与微内核调用映射:
| POSIX 调用 | 微内核调用 | 描述 |
|---|---|---|
| pthread_create() | ThreadCreate() | 创建新线程 |
| pthread_exit() | ThreadDestroy() | 销毁线程 |
| pthread_join() | ThreadJoin() | 连接线程,等待退出状态 |
| pthread_cancel() | ThreadCancel() | 在下一个取消点取消 |
| — | ThreadCtl() | 更改 QNX OS 特定线程特性 |
| pthread_mutex_lock() | SyncMutexLock() | 锁定互斥锁 |
| pthread_mutex_unlock() | SyncMutexUnlock() | 解锁互斥锁 |
| pthread_cond_wait() | SyncCondvarWait() | 等待条件变量 |
| pthread_cond_signal() | SyncCondvarSignal() | 信号条件变量 |
| pthread_getschedparam() | SchedGet() | 获取调度参数/策略 |
| pthread_setschedparam() | SchedSet() | 设置调度参数/策略 |
2.5 线程调度
调度决策何时发生? —— 微内核在因"内核调用、异常或硬件中断"进入时进行调度。
三种抢占情况:
| 情况 | 行为 |
|---|---|
| 线程阻塞 | 从运行数组中移除,下一个合格线程运行。解除阻塞时加入就绪队列末尾 |
| 线程被抢占 | 高优线程就绪时,被抢占线程放入本优先级就绪队列开头 |
| 线程主动让出 | 通过 sched_yield(),线程放入本优先级就绪队列末尾 |
全局调度:线程"在所有进程中全局调度"——不区分属于哪个进程。
调度优先级:每个线程分配一个优先级,调度器通过"比较 READY 线程的优先级"选择下一个线程。
2.6 同步服务
| 原语 | 进程间支持 | 描述 |
|---|---|---|
| Mutexes | ✅(带安全警告) | 线程间数据的独占访问 |
| Condition Variables | ✅ | 在条件满足前阻塞线程于临界区 |
| Barriers | ✅(带安全警告) | 强制线程在特定点等待直到全部到达 |
| Reader/Writer Locks | ✅(带安全警告) | 多读单写锁 |
| Semaphores | ✅ | 通过 post/wait 控制线程唤醒/睡眠 |
| Send/Receive/Reply | ✅ | 通过阻塞特性实现隐式同步 |
| Atomic Operations | ✅ | 硬件直接处理,不可中断 |
所有列出的原语由内核实现(原子操作除外,由处理器直接处理)。
注意:互斥锁、条件变量、屏障、读写锁和信号量"只能分配在正常内存映射中"——在未缓存内存中分配会导致调用时发生故障。
2.7 时钟与定时器服务
核心内核调用:
| 内核调用 | POSIX 等价 | 描述 |
|---|---|---|
| ClockTime() | clock_gettime/settime | 获取/设置系统时间 |
| ClockCycles() | 无 | 返回自由运行的 64 位周期计数器值 |
| ClockId() | clock_getcpuclockid | 返回进程/线程的 CPU 时间时钟 ID |
关键细节:
- 内核内部使用"无符号 64 位数计从 1970 年 1 月 1 日开始的纳秒数"——避免 2038 年问题
- 覆盖范围从 1970 年到 2554 年
- 多核系统上 ClockCycles() 的硬件必须在所有处理器上同步
定时器类型:
- 绝对定时器 (absolute timer) — 特定固定时刻触发
- 相对定时器 (relative timer) — 从当前时间偏移触发
- 重复定时器 (repeating timer) — 自动重载并继续运行
2.8 中断处理
QNX OS 实现了"调度用户线程处理硬件中断的低延迟路径"。
中断处理流程:
- 硬件设备断言中断
- 可编程中断控制器 (PIC) 处理
- PIC 在 CPU 核心上断言中断
- 触发异常,内核异常处理程序执行
- 处理程序识别中断,为每个关联线程"投递内部信号量标记线程为 READY"
- 处理程序屏蔽中断并发出 EOI
- 解除阻塞的线程按正常调度规则调度
- 调度的中断服务线程 (IST)“处理其硬件设备、取消中断屏蔽、然后阻塞等待下一个中断”
IST 延迟:“从硬件中断断言到 IST 返回内核后阻塞等待中断后第一条指令执行的时间”。
2.9 CPU Offlining
允许特权应用阻止 procnto 使用某个 CPU。
用途:
- 降低工作负载时关闭 CPU
- 临时在 QNX 外运行软件(如 CPU 诊断)
- 使系统休眠
使 CPU 下线步骤:
- 设置线程的处理器亲和性(runmask)
- 设置策略为 SCHED_OFFLINING,优先级高于该 CPU 上除 IPI IST 外的所有线程
- 使用 TimerDelegate() 卸载软件定时器
- 调用 SchedCtl(SCHED_PROCESSOR_OFFLINE)
恢复 CPU 上线步骤:
- 通过 TimerDelegate(_NTO_TIMER_RECLAIM) 回收定时器
- 调用 SchedCtl(SCHED_PROCESSOR_ONLINE)
- 将策略设置为 SCHED_FIFO,优先级降低到时钟 IST 优先级以下
高优先级下受限的 C 库函数(仅允许):
TimerDelegate(), SchedCtl(), InterruptDisable(), InterruptEnable(), ClockCycles(), clock_gettime*() with CLOCK_MONOTONIC/CLOCK_REALTIME, atomic_*()
第三部分:进程间通信 (IPC)
3.1 概述
IPC"在将微内核从嵌入式实时内核转变为完整 POSIX 操作系统中发挥着基础作用"。IPC 是"将组件连接成一个有机整体的胶水"。
IPC 服务与实现位置:
| 服务 | 实现位置 |
|---|---|
| 消息传递 | 内核 |
| 信号 | 内核 |
| POSIX 消息队列 | 内核 + 外部进程管理 |
| 共享内存 | 进程管理器 |
| 管道 (Pipes) | 外部进程 |
| FIFO | 外部进程 |
3.2 同步消息传递
QNX OS 中 IPC 的主要形式,基于 Send/Receive/Reply 模型。
客户端行为:
- MsgSend() → 服务器尚未 MsgReceive():进入 SEND-blocked 状态
- 服务器 MsgReceive() 后:转为 REPLY-blocked
- 服务器 MsgReply() 后:变为 READY
- 如果客户端发送时服务器已阻塞于 MsgReceive():“客户端线程立即变为 REPLY-blocked,完全跳过 SEND-blocked 状态”
服务端行为:
- MsgReceive() 无待处理消息:变为 RECEIVE-blocked
- 有消息已发送:“MsgReceive() 立即返回消息”——服务器不阻塞
- MsgReply() 从不阻塞服务器
MsgReply() vs MsgError():
- MsgReply():返回状态 + 零或更多字节数据
- MsgError():仅返回状态
- 两者都非阻塞
3.3 通道与连接
通道和连接是 QNX 消息传递架构的基础。
| 概念 | 创建函数 | 描述 |
|---|---|---|
| Channel | ChannelCreate() | 服务器接收消息的抽象对象 |
| Connection | ConnectAttach() | 客户端附加到通道的关系 |
服务端事件循环模式:
chid = ChannelCreate(flags);
SETIOV(&iov, &msg, sizeof(msg));
for(;;) {
rcv_id = MsgReceivev(chid, &iov, parts, &info);
switch(msg.type) { /* 处理消息 */ }
MsgReplyv(rcv_id, &iov, rparts);
}
通道的三个线程队列:
| 队列 | 类型 | 描述 |
|---|---|---|
| Receive list | LIFO | 等待消息的线程 |
| Send list | 优先 FIFO | 已发送但尚未被接收的消息 |
| Reply list | 无序 | 已被接收但尚未回复的消息 |
3.4 脉冲 (Pulses)
脉冲是"固定大小的非阻塞消息",携带 9 字节有效载荷:
- 8 位(1 字节)代码
- 64 位(8 字节)数据
“脉冲通常用于允许服务器通知客户端而不阻塞它们”。
3.5 优先级继承与消息
QNX OS 使用消息驱动的优先级继承机制防止优先级反转。
工作原理:
- 服务器收到消息时,其有效优先级变为与最高优先级发送者相同
- 接收触发提升:低优客户端发送时,服务器接收消息时优先级改变
- 发送触发提升:高优客户端发送时,服务器优先级在发送时改变
- 服务器回复后优先级不会自动恢复
禁用优先级继承:
在 ChannelCreate() 时指定 _NTO_CHF_FIXED_PRIORITY 标志。
3.6 事件
内核拥有"处理事件的子系统"。所有通知方法都构建在"一个单一的、丰富的事件子系统之上"。
事件来源:
- 其他线程调用 MsgDeliverEvent()
- 定时器到期
- POSIX 消息队列"从空变为非空"
事件类型:
- QNX OS 脉冲
- 中断
- 各种信号类型
- “强制解除阻塞事件”
sigevent 机制:
客户端可以给服务器一个称为 sigevent 的数据结构作为"cookie"。服务器随后调用 MsgDeliverEvent() 时,“微内核将 cookie 中编码的事件类型设置在客户端线程上”。
安全/注册事件:
客户端可以注册事件以确保"只获得它想要的事件,并且没有人篡改过它们"。使用 MsgRegisterEvent() 注册,MsgUnregisterEvent() 注销。
3.7 信号
QNX 实现 “32 个标准 POSIX 信号和 POSIX 实时信号,来自内核实现的 64 个统一功能信号集”。
微内核调用到 POSIX 包装器:
| 内核调用 | POSIX 包装器 | 目的 |
|---|---|---|
| SignalKill() | kill(), pthread_kill(), raise(), sigqueue() | 在进程组、进程或线程上设置信号 |
| SignalAction() | sigaction() | 定义接收信号时的动作 |
| SignalProcmask() | sigprocmask(), pthread_sigmask() | 更改线程的信号屏蔽掩码 |
| SignalSuspend() | sigsuspend(), pause() | 阻塞直到信号处理程序触发 |
| SignalWaitinfo() | sigwaitinfo() | 等待信号并返回信息 |
多线程信号规则:
- 同步信号 (SIGSEGV 等) 始终传递到故障线程,不能被线程的信号掩码阻止
- 信号动作在进程级别维护
- 每个线程维护自己的信号掩码
- 针对线程的信号仅到达该线程
- 针对进程的信号到达"第一个未阻塞该信号的线程"
3.8 POSIX 消息队列
“一组非阻塞消息传递工具”,需要 mqueue 服务器运行。
与本地 QNX 消息的关键区别:
| 特性 | POSIX 消息队列 | QNX 本地消息 |
|---|---|---|
| 阻塞 | 发送者不需要阻塞 | 同步阻塞 |
| 排队 | 多消息可排队 | 无内置排队 |
| 持久性 | 独立于使用进程 | 与进程关联 |
| 消息长度 | 固定 | 无限制 |
| 优先级继承 | 不支持 | 支持 |
| 已知发送者 | 未知 | 已知 |
文件系统映射:所有消息队列出现在 /dev/mqueue/ 下。
3.9 共享内存
提供最高带宽的 IPC 机制。“一旦创建了共享内存对象,具有访问权限的进程可以使用指针直接读写”。
同步要求:通常与互斥锁或信号量结合使用,以原子化更新共享数据。
适用同步原语:
- 信号量(POSIX 实时标准)
- 互斥锁(POSIX 线程标准)—— “通常比信号量更高效”
效率:更新大量数据块时最高效。
3.10 管道与 FIFO
| 特性 | Pipes | FIFOs |
|---|---|---|
| 命名 | 未命名 | 命名永久文件 |
| 生命周期 | 关闭后移除 | 持久存在 |
| 创建 | pipe() / popen() | mkfifo() / mkfifo |
| 移除 | 自动 | remove() / unlink() / rm |
| 典型用途 | 兄弟进程间单向数据流 | 无关进程间通信 |
前提条件:管道资源管理器 (pipe) 必须运行。
第四部分:微内核 Instrumentation
概述
微内核镜像 procnto-smp-instr 包含集成的跟踪和分析机制,用于实时系统监控。在单 CPU 和 SMP 架构上均可工作。Instrumentation “uses very little overhead and gives exceptionally good performance.”
无侵入设计
无需修改源代码即可监控程序与内核的交互。用户可选择跟踪多少交互:
- 内核调用
- 线程/进程状态变化
- 其他系统活动
- 中断
所有这些被监控的活动统称为 事件 (events)。
事件控制
实时系统生成大量事件,数据量可能"令人不知所措(就数据量、处理需求和存储资源而言)"。但用户有直接的控制手段来调节数据发射量。
数据解释
每个事件记录包含:
- 高精度时间戳
- 事件来源 CPU ID 号
这使得诊断困难的时序问题成为可能,特别是"更可能在多处理器系统上发生"的问题。
主动跟踪
除了内核被动、无侵入地监控进程/线程/系统状态外,应用程序可通过专用 API 主动影响事件收集过程。
Trace 库函数
| 函数 | 用途 |
|---|---|
TraceEvent() |
核心跟踪入口 |
trace_func_enter() |
标记函数进入 |
trace_func_exit() |
标记函数退出 |
trace_here() |
在当前位罝插入跟踪点 |
trace_logb() / trace_logbc() |
记录二进制数据 |
trace_logf() |
记录格式化数据 |
trace_logi() |
记录整数数据 |
trace_nlogf() / trace_vnlogf() |
命名格式化日志 |
traceparser() |
解析跟踪数据 |
traceparser_init() / traceparser_destroy() |
解析器生命周期 |
traceparser_cs() / traceparser_cs_range() |
获取当前/范围状态 |
traceparser_debug() |
调试解析器输出 |
traceparser_get_info() |
检索解析器信息 |
第五部分:进程管理器 (procnto)
概述
进程管理器负责创建和管理多个 POSIX 进程,每个进程可包含多个 POSIX 线程。它与微内核捆绑在单个模块 procnto 中,是所有运行时 QNX 系统必需的。
三大核心职责
| 域 | 描述 |
|---|---|
| 进程管理 | 进程创建、销毁和进程属性(如 UID/GID) |
| 内存管理 | 内存保护能力、共享库、POSIX 进程间共享内存原语 |
| 路径名管理 | 管理资源管理器可附加到的路径名空间 |
I/O 资源不属于微内核本身,而是由可在运行时启动的资源管理器进程提供。通过标准 API,资源管理器可将路径名空间的子集作为自己的权限域。
架构关键点
- 用户进程通过内核调用直接访问微内核函数
- 进程管理器函数通过 发送消息到 procnto(使用
MsgSend*()内核调用)访问 - 在 procnto 内执行的线程与其它进程中的线程以完全相同的方式调用微内核——共享地址空间不意味着特殊或私有接口
- 所有线程使用相同的一致内核接口,且在调用微内核时都执行特权切换
第六部分:动态链接
基本概念
动态链接让多个程序引用同一个共享库实例,而非各自包含一份拷贝,从而节省系统内存。
关键组件
| 组件 | 描述 |
|---|---|
| 链接器 (ld) | 编译后组合目标文件和归档文件,重定位数据并解析符号引用 |
| 运行时链接器 (ldqnx) | 程序运行时查找并加载共享对象。路径 /usr/lib/ldqnx-64.so,需包含在 OS 镜像中 |
静态 vs 动态链接
| 特性 | 静态链接 | 动态链接 |
|---|---|---|
| 绑定时机 | 链接时 | 运行时 |
| 文件扩展名 | .a(归档) |
.so(共享对象) |
| 可执行文件 | 完全绑定 | 部分绑定(链接器仅记录函数在哪个共享对象中) |
| 适用场景 | 不确定运行时库版本;测试新库 | 节省内存;多程序共享 |
运行时灵活性示例(通用磁盘驱动)
- 驱动启动后探测硬件,发现硬盘
- 动态加载
io-blk代码处理磁盘块 - 发现两个分区(DOS + Power-Safe)
- 运行时根据分区类型动态加载
fs-dos.so和fs-qnx6.so
通过推迟决定调用哪些函数,增强了灵活性并减小了驱动体积。
相关 API
dlopen(), dlclose(), dlsym(), dladdr(), dlerror()
第七部分:资源管理器 (Resource Managers)
概述
资源管理器是 QNX OS 中的用户级进程,可动态启动和停止,为各种设备(硬件和虚拟)提供接口。
关键区别: 与传统操作系统中的"设备驱动程序"不同,QNX 资源管理器与内核之间没有特殊绑定——“a resource manager looks just like any other user-level program。”
管理的设备类型
| 类型 | 示例 |
|---|---|
| 硬件设备 | 串口、并口、网卡、磁盘驱动器 |
| 虚拟设备 | /dev/null、网络文件系统、伪终端 (pty) |
客户端通信机制
由于 QNX OS 是分布式微内核系统,几乎所有非内核功能都由用户可安装的程序提供,因此客户端程序与资源管理器之间需要清晰且定义良好的接口。
资源管理器架构
关键特性:
- 支持路径名空间映射 (pathname space mapping)
- 定义良好的资源管理器接口
- 提供通用资源管理器函数的库集合
这些特性"offers the developer unprecedented flexibility and simplicity in developing drivers for new hardware"——对嵌入式系统至关重要。
第八部分:文件系统
架构
QNX 文件系统作为内核之外的资源管理器运行。应用程序通过消息传递与它们交互。
关键架构特性:
- 文件系统可动态启动和停止
- 多个文件系统可并发运行
- 应用程序看到单一统一的路径名空间和接口
- 每个文件系统在路径名空间声明挂载点
- 资源管理器验证单个路径名组件的权限和访问授权
支持的文件系统类型
| 文件系统 | 驱动 | 读写 | 特性 |
|---|---|---|---|
| Power-Safe (fs-qnx6.so) | 分区 177/178/179 | R/W | 防断电损坏,日志式可靠性 |
| QCFS (fs-qcfs.so) | 分区 181 | 只读 | 文件和元数据压缩 |
| QTD (fs-qtd.so) | 分区 185 | 取决于配置 | 安全启动环境中的完整性保护 |
| IFS | 内置(启动镜像) | 只读 | OS 镜像内文件,位于 /proc/boot |
| DOS FAT (fs-dos.so) | 分区 1/4/6/11/12/14 | R/W | FAT12/16/32 透明访问 |
| Ext2 (fs-ext2.so) | 分区 131 | R/W | Linux 磁盘分区透明访问 |
| UDF/ISO 9660 (fs-udf.so) | 无 | 只读 | UDF + ISO 9660 (Joliet/RRIP) |
| FFS3 (devf-*) | NOR Flash | R/W | QNX 特有的 POSIX 式闪存文件系统 |
| NFSv3 (fs-nfs3) | 网络 | R/W | 客户端文件访问转换为 NFS 请求 |
| Squashfs (fs-squash.so) | 只读 | 只有读 | 数据/inode/目录压缩 |
| Shmem (/dev/shmem) | 内核 | R/W | 每个 QNX 系统都有,不支持许多 POSIX 语义 |
第九部分:字符 I/O
io-char 架构
io-char 库充当应用程序与设备驱动之间的中介。每个字符设备关联三个 FIFO 队列:
三队列机制
| 队列 | 方向 | 描述 |
|---|---|---|
| 原始输入队列 | 驱动 → io-char | 驱动放入接收数据;io-char 在应用请求时消费。支持原始模式和编辑模式 |
| 输出队列 | io-char → 驱动 | io-char 放入输出数据;驱动在传输时消费。实现 write-behind 策略 |
| 规范队列 | io-char 内部 | 仅在编辑模式下使用。大小决定设备可处理的最大编辑输入行长度 |
Write-Behind 策略
io-char 仅在输出缓冲区满时才阻塞写入进程,在此之前数据异步排队。新数据加入时 io-char 调用驱动的受信例程"唤醒"可能空闲的驱动。
职责分工
| 组件 | 职责 |
|---|---|
| 设备驱动 | 向输入队列添加接收数据 / 从输出队列消费并传输数据 |
| io-char 模块 | 高层逻辑:输出传输何时暂停、接收数据如何回显等 |
字符设备类型
| 设备 | 驱动 |
|---|---|
| 控制台 | devc-con, devc-con-hid |
| 伪终端 | devc-pty |
| 串口 | devc-ser8250, devc-serpci, devc-serusb |
第十部分:网络架构
核心设计原则
网络服务在内核之外运行,与其他服务进程相同。提供"单一统一接口,无论配置和网络数量如何"。
关键能力
- 网络驱动可动态启动和停止
- 多种协议可"以任何组合"共存
子系统组件
| 组件 | 描述 |
|---|---|
网络管理器 (io-sock) |
原生网络子系统可执行文件 |
| 共享库模块 | 运行时加载的一个或多个模块 |
| 协议和驱动 | 包含在模块中(如 devs-em.so) |
详细架构在线程模型方面参考 High-Performance Networking Stack User’s Guide。
第十一部分:TCP/IP 网络
TCP/IP 栈是 io-sock 网络栈的一部分,“uses the common FreeBSD API”。Internet 协议的详细信息参考 High-Performance Networking Stack User’s Guide 的 Protocols 章节。
第十二部分:什么是实时 (Real Time)
定义
实时系统是指"计算的正确性不仅取决于计算的逻辑正确性,还取决于结果生成的时间"。如果时序约束未满足,系统失败已经发生。
硬实时 vs 软实时
| 类型 | 定义 |
|---|---|
| 硬实时 (Hard) | “延迟的计算无价值,延迟的后果可能对系统造成灾难”。所有活动必须按时完成 |
| 软实时 (Soft) | 价值"随延迟而递减"。可容忍一定程度的延迟,只要价值未降到零 |
仅偏好运行实时活动但未正确考虑不可调度活动的 OS 应称为 准实时 (quasi-realtime) 或 伪实时 (pseudo-realtime)。
RTOS 五项要求 (OSRs)
- 任务的固定优先级抢占式调度
- 同步原语的优先级继承或优先级天花板模拟
- 内核必须是可抢占的
- 中断必须有固定的延迟上界;需要嵌套中断支持
- OS 服务必须以客户端优先级执行——所有依赖服务继承该优先级,优先级反转避免应用于所有共享资源
RTOS vs 常规 OS
关键区别是可预测性 (predictability)。常规 OS(如 Linux)使用公平策略调度线程,不建立实时线程的优先级优势。在内核调用期间优先级信息通常丢失,导致不可预测的延迟。
QNX 微内核架构直接满足所有五项需求:
- 以固定优先级管理线程(通过线程置换抢占)
- 所有设备驱动和 OS 服务以独立进程存在,通过同步消息传递 IPC 访问——接收者继承客户端优先级
- 这使原始实时活动的优先级贯穿所有服务和设备驱动请求 (OSR 5)
相关参考
| 文档 | 用途 |
|---|---|
| Getting Started | 进程、线程、消息传递入门 |
| Programmer’s Guide | 编程指南 |
| SAT User’s Guide | Instrumentation 详细使用 |
| io-sock User’s Guide | 网络栈详情 |
| Writing a Resource Manager | 资源管理器开发 |
| QNX Filesystem for Safety | QTD 安全文件系统 |
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)