1. QNX 是什么:把内核做小,把可靠性做大
刚接触 QNX 的人,十有八九是从"实时操作系统"这个标签进来的,然后卡在第一步——这东西到底跟 Linux 有什么不一样,为什么汽车厂商愿意为它付钱。我第一次摸 QNX 是因为要在一台老工控机上跑一个运动控制程序,Linux 上跑得挺欢,但一遇到高负载就偶发丢帧,排查到最后一根筋搭错了才发现问题不在代码,而在调度器。后来换到 QNX,同样的代码,抖动从毫秒级掉到几十微秒,那一下我才真正理解"实时"两个字的重量。
所以这篇东西不打算写成产品说明书。我按一个从业者的路子来:先把 QNX 的核心设计讲透,让你明白它为什么值这个钱;然后手把手在 VirtualBox 里把 QNX 装起来跑通,包括网卡、显示、宿主机传文件这些真上手才会撞上的坑。标题写的是"什么是 QNX 系统,如何在 VirtualBox 中安装 QNX 系统",这两件事其实是连着的——你不理解它的架构,装完之后连进程列表都看不懂,更别说调驱动。适合谁看:想入门实时操作系统的嵌入式软件工程师、准备做车载或工控项目的开发者,以及单纯想在自己笔记本上开个虚拟机玩玩 QNX、不想动真机的人。
1.1 内核里只剩四件事
QNX Neutrino 的微内核体积在几十 KB 这个量级,你可以把它理解成一个"只负责维持秩序的小物业":它管线程调度、管进程间通信(IPC)、管同步原语(互斥量、信号量、条件变量)、管中断分发。就这四件。剩下的东西——文件系统、TCP/IP 协议栈、所有设备驱动、USB 栈、图形系统、甚至部分电源管理——统统作为普通的用户态进程跑在内核外面。
这个设计带来的直接结果是:任何一个服务进程挂掉,内核完全不受影响。文件系统服务崩了,内核还在调度,你的高优先级控制线程照样按时执行;网卡驱动崩了,重启一下那个驱动进程就行,不需要整机重启。对比一下 Linux 的单体内核:一个写得糟糕的字符设备驱动走了野指针,通常就是内核 panic,全盘皆输。这就是为什么医疗设备、列车信号系统这种"停一次就是事故"的场景愿意选 QNX。
代价也很清楚。所有服务进程之间要靠消息传递通信,多了一次内存拷贝和上下文切换的开销,同样的业务逻辑在 QNX 上 CPU 占用通常比 Linux 高一些。所以 QNX 从来不是拼吞吐量的选手,它拼的是可预测性。
1.2 一次驱动崩溃在 QNX 上是什么体验
我给你描述一个我真实遇到过的场景。一块定制采集卡,驱动是我自己写的资源管理器(resource manager),跑在用户态。测试阶段驱动里有个队列长度算错了,连续跑两小时后触发了越界访问,进程直接收到 SIGSEGV 死了。当时的反应是"完了,得重启",结果发现系统还在跑,只是那台采集设备的 /dev 节点消失了,其他服务全部正常。
我做的事就是重新启动那个驱动进程,设备节点恢复,业务继续。整个过程几十秒,不需要重启机器,不需要重新加载内核模块。这个特性在 Linux 上想都不敢想——驱动是内核模块,出了这种事只能重启。
从工程角度看,这意味着你可以把不同关键等级的驱动隔离开:把摄像头、蓝牙这种"非关键"驱动放在低优先级、低权限的进程里,就算它们内存泄漏或者死循环,也吃不到控制线程的 CPU 时间片。QNX 里可以通过进程级别的 CPU 亲和性绑定和优先级天花板把这种隔离做得非常干净。这是我觉得 QNX 最值钱的地方,比"实时"两个字还值钱。
1.3 实时性不是"跑得快"
很多人把实时理解成"响应快",这是个误解。实时指的是确定性——在最坏情况下,从事件发生到处理线程开始执行的时间上限是可计算、可保证的。一个平均响应 10 微秒但偶尔飙到 5 毫秒的系统,在实时语境下比一个稳定在 100 微秒的系统差得多。
QNX 做到这一点靠几件事。第一是优先级驱动的抢占式调度,内核里没有"不可抢占区"这种大块头,调度延迟基本恒定。第二是优先级继承,低优先级线程持有高优先级线程需要的互斥量时,会被临时提升优先级,避免优先级反转——这个坑在火星探路者号上真实翻过车,QNX 直接在内核层面处理掉了。第三是消息传递本身被设计成同步的、带优先级传递的机制,客户端发消息给服务端时,服务端线程会继承客户端的优先级,避免"服务线程优先级太低导致高优先级请求排队"的问题。
这三点加起来,才是 QNX 在汽车座舱里能同时跑仪表、娱乐、倒车影像还不卡的原因。你在 Linux 上用 PREEMPT_RT 也能做到接近的效果,但要调的参数和要躲的坑会多不少。
1.4 版本谱系:6.5、7.1、8.0 该碰哪个
现在说选型,因为这直接决定你 VirtualBox 里装哪个版本。
QNX Neutrino 6.5.0:x86 32 位,免费公开存档,可以直接下载 ISO 在 PC 上安装。它的图形系统是 Photon microGUI,界面风格很有年代感,但对新手最友好——因为它是唯一一个你不用申请任何授权就能完整装起来跑的版本。我建议入门就从这里开始。
QNX SDP 7.1:主流商用版本,64 位和 32 位都有,图形系统换成了 QNX Screen 加 Qt,需要向 BlackBerry QNX 申请试用授权,通常给 30 天。它的 BSP(板级支持包)覆盖了大量车规芯片。
QNX SDP 8.0:最新的,支持 64 位 ARM 和 x86_64,POSIX 符合度更高,官方还给了树莓派这类开发板的免费镜像。但它是面向真实硬件的,VirtualBox 上跑 x86_64 镜像需要授权,不适合拿来练手。
一句话结论:想学概念和命令,装 6.5;想做项目,申请 7.1 试用;真上车,用 8.0 配官方 BSP。
2. 装之前把这三件事想清楚
动手之前有三件事必须提前定下来,否则做到一半会发现整个虚拟机要推倒重来。我吃过一次亏,当时图省事用了默认的 SATA 控制器,结果 QNX 6.5 的安装程序压根找不到硬盘,折腾了半小时才反应过来是老系统的驱动只认 IDE。
2.1 镜像从哪来,怎么验
QNX Neutrino 6.5.0 的安装镜像在 BlackBerry QNX 官网的历史版本存档里,需要注册一个账号才能拿到下载链接。有些高校的教学资源站和开源镜像站也留有存档,文件名的典型格式是qnxnc650.iso或者带有 SDP 版本号的长文件名,体积在几百 MB 级别。
下载完一定要校验。官网上会给出 MD5 或 SHA256,用系统自带的certutil -hashfile(Windows)或sha256sum(Linux)对一下。我见过下载不完整导致安装到一半卡在"复制文件"阶段、进度条不动的情况,最后排查出来是 ISO 尾部损坏。这种问题最容易误判成虚拟机配置问题,白白浪费时间。
顺带说一句:QNX 6.5 的安装盘本身就是一张可启动的 Live 光盘。它启动后直接进入 QNX 环境,你可以在里面先用pidin看看进程、用pci看看设备,确认这个版本对你的虚拟硬件识别正常,再开始装。这个习惯我强烈建议保留——先试跑,再安装。
2.2 VirtualBox 版本与图形控制器
VirtualBox 版本这件事,网上流传的 5.2.44 确实是个经典稳定版,功能齐全、对老 guest 系统兼容性好,很多教程都是基于它写的。但我不建议新手去专门找这个版本装,因为老版本在 Windows 11 和新版内核上有签名和兼容问题,装完大概率还会撞上后续章节要讲的 rc=-1908 报错。
我的建议是:用当前主流的 6.1 或 7.x 稳定版。理由是对老系统的 BIOS 模拟逻辑没有本质变化,而新版本在处理 USB 直通、网络类型切换这些日常操作上省心得多。
真正需要你手动改的是图形控制器。VirtualBox 提供三种:VMSVGA、VBoxSVGA、VBoxVGA。QNX 6.5 的 Photon 图形系统走的是 VESA BIOS 扩展(VBE)来设定分辨率,而 VMSVGA 这个控制器是纯软件模拟,不提供 VBE 接口,选它的话装完之后图形界面基本上起不来。所以务必要选VBoxSVGA(7.x 里的默认选项之一)或者 VBoxVGA。这一步选错,后面 crttrap 会一直报"找不到可用显示模式"。
2.3 虚拟机规格的参数账
内存给多少?QNX 6.5 官方给的最低要求是 128MB,但那是在真实硬件上跑最小系统的数字。在 VirtualBox 里跑,宿主机的模拟开销加上 Photon 图形系统,我建议直接给1024MB。给 512MB 也能跑,但一旦同时开图形界面和编译,就会开始换页,体验很差。给 2048MB 是浪费,QNX 6.5 是 32 位系统,单进程地址空间有限。
CPU 核心数:1 个。这里不是省资源,是省事。QNX 6.5 的 SMP 版本(procnto-smp)确实支持多核,但装在 VirtualBox 里跑多核,再加上 VirtualBox 自身的调度层,容易出现时序抖动,反而让"实时系统"变得不实时。先把单核跑通,理解了再用第二个虚拟机试 SMP。
硬盘:4GB 固定大小 VDI,控制器必须是 IDE。为什么是 4GB?QNX 6.5 完整安装(含开发工具和图形)大约占 1.5 到 2.5GB,留一倍余量足够。为什么不动态分配?因为 QNX 的 devb-eide 驱动在识别虚拟磁盘的几何结构时,动态 VDI 在某些版本上会报告异常的 CHS 参数,固定大小最稳。为什么必须 IDE?前面说过了,QNX 6.5 时代的块设备驱动针对 ATA/IDE 编写,AHCI(SATA)的支持在 6.5 上并不完整。VirtualBox 新建向导默认可能给 SATA,你要在"存储"设置里删掉 SATA 控制器,手动添加一个 IDE 控制器,把硬盘挂到 IDE 主通道上。
3. VirtualBox 里装 QNX Neutrino 6.5 的完整流程
前面三件事定好之后,剩下的就是按部就班。我把整个流程拆成五步,每一步都标注了容易出错的点。
3.1 新建虚拟机:IDE 是关键
打开 VirtualBox,点"新建"。名称随便写,比如qnx65。类型选Other,版本选Other/Unknown——不要选成 Linux 或 BSD,QNX 不在列表里。内存 1024MB。
硬盘这一步选"现在创建虚拟硬盘",类型 VDI,存储方式选"固定大小",容量填 4096MB。创建完先别急着启动,进"设置"里改两处。
存储设置:默认会有一个 SATA 控制器,选中它点右边的减号删掉。然后点"添加控制器",下拉里选IDE。接着在 IDE 控制器下点"添加光盘",选"选择磁盘"→"注册",载入你的 QNX 6.5 ISO;再点"添加硬盘",选刚才创建的 VDI 文件。最终结构应该是 IDE 控制器下挂着一个光驱(IDE 主通道)和一个硬盘(IDE 从通道)。
显示设置:图形控制器选 VBoxSVGA,显存调到 16MB 以上,勾选"启用 3D 加速"其实没必要,反而可能引入问题,建议不勾。
还有一个容易被忽略的点:系统设置里的"启用 EFI"必须关掉。QNX 6.5 的启动加载器是传统 BIOS 引导,走 EFI 直接黑屏。
3.2 从 ISO 启动到安装向导
启动虚拟机,屏幕上会出现 QNX 的启动加载画面,通常有一个很短的引导菜单,默认几秒后自动进入。加载过程会滚过一大堆驱动探测信息,其中夹杂着devb-eide、io-net、io-graphics的加载记录,这些信息后面排查问题时会用到,建议第一次跑的时候暂停看一眼。
成功的话,你会看到 Photon 桌面起来了,背景是那种很有年代感的灰蓝色。桌面上有一个安装程序的图标,双击它就开始安装向导。如果你用的是纯文本模式(有些精简镜像不带图形),可以直接在终端里运行installer或者/usr/bin/install启动。
向导第一步是语言和键盘布局,选英文最稳,中文在这个版本上支持得不完整,容易出乱码。然后是磁盘选择,向导会列出检测到的磁盘,正常情况下应该只显示一个,就是你的 4GB VDI。
提示:如果这一步磁盘列表是空的,99% 是存储控制器的问题,回去检查是不是挂到 IDE 上了,以及"启用 EFI"有没有关。
3.3 分区与文件系统参数的填写
分区这一页是新手最容易犯难的地方。QNX 的安装向导会提供几种模式,我建议直接选"使用整个磁盘",让它自动创建分区和文件系统。它会创建一个 QNX 类型的主分区(分区类型号是 77/78/79 这一族),然后在里面创建 QNX6 文件系统。
如果你要手动分区,需要填几个参数,我解释一下它们是干什么的。
块大小(block size):默认 4096 字节。这个值决定文件系统一次读写的最小单位。小文件多的场景(比如/etc下一堆配置文件)用 4096 比较合适;如果硬盘里主要放大文件,比如镜像和日志,可以调到 8192 减少块数量。新手别动,用默认。
inode 数量:QNX6 文件系统在创建时就固定了 inode 总数,后期不能动态增加。安装程序通常会按分区大小给一个估算值。你要做的是估一下这个小系统最终会有多少文件——完整安装大概两三万个文件,再加上你自己编译产生的中间产物,给到 6 万左右比较安全。inode 给少了,磁盘还有空间但就是创建不了新文件,报 "no space left on device" 却看不出哪里满,这个坑我踩过。
块预留比例:默认大约 5%,是给文件系统元数据和碎片预留的。4GB 分区上没必要改。
挂载点配置上,QNX 6.5 的标准做法是把整个系统装在/下,如果分区够大也可以单独分/usr。压缩包大的家用镜像建议别分,简单直接。
3.4 首次启动与 root 配置
文件复制完成之后,向导会提示重启。这时候要做的第一件事是在 VirtualBox 的存储设置里把 ISO 弹出来(把光驱指向"空"),否则机器会又从光盘启动,你以为安装失败了。
重启后进入 QNX 的首次配置。系统会要求你设置 root 密码。QNX 6.5 的密码有长度限制,早期版本密码超过 8 位会被截断,这是个历史遗留问题,你输一个 8 位以内的强密码就好,别用 20 位的,否则下次登录输对了也进不去,还以为是键盘布局问题。
接着是创建普通用户。QNX 默认不让 root 直接登录图形界面,需要建一个普通用户。用户名用全小写,避免特殊字符。用户的家目录会建在/home/用户名下面。
第一次登录进去,我通常先跑几条命令确认系统状态:
pidin info # 查看系统基本信息、CPU、内存、启动时间 pidin ar # 查看所有进程和线程,类似 ps -ef use -l # 列出所有已注册的设备资源管理器 sin # 查看系统信息,包括内核版本pidin ar的输出很有信息量。你会看到procnto是内核进程,它下面挂着几十个线程;devb-eide是块设备驱动进程;io-net是网络栈;io-graphics是图形。整整齐齐都是用户态进程,没有一个是内核模块。这个列表看多了,你对微内核的理解会从概念变成直觉。
3.5 点亮 Photon 图形界面
如果安装时选了图形组件,重启后应该自动进桌面。但如果进不去,屏幕上只给你一个文本控制台,那大概率是显示模式没配对。
QNX 6.5 有一个专门的工具叫crttrap,作用是探测显卡支持的显示模式并生成配置文件。进入系统后,在终端里执行:
crttrap clear # 清掉旧配置 crttrap trap # 探测可用模式 crttrap query # 列出探测结果trap的过程会滚一堆输出,最后告诉你生成了/etc/system/config/graphics-traplist。如果探测成功,直接运行ph就能进 Photon 桌面。
如果探测失败或者分辨率不对,可以用 VirtualBox 的自定义视频模式来补。关掉虚拟机,在宿主机命令行里执行:
VBoxManage setextradata "qnx65" "CustomVideoMode1" "1024x768x32"然后启动,再用crttrap trap重新探测。这条命令本质上是在虚拟显卡的 VBE 模式表里额外注册了一个 1024x768 32 位的模式,QNX 的 vesabios 驱动扫描时就能发现它。这个技巧在 7.x 版本的 VirtualBox 上依然有效,实测很稳。
4. 装完必须打通的三件事:网络、显示、传文件
系统跑起来只是开始,能干活才算数。这一节讲的是装完之后最需要马上打通的三件事。
4.1 网卡驱动与 io-net 配置
QNX 6.5 的网络架构和 Linux 完全不同。它没有"网卡驱动直接编进内核"这种事,而是由io-net这个进程加载不同的驱动模块(.so文件),形成一个协议栈管道。
VirtualBox 提供的网卡类型里,对 QNX 6.5 最友好的是两种:Intel PRO/1000 MT Desktop(模拟 e1000 芯片)和PCnet-FAST III(模拟 AMD Am79C973)。我建议先用 PCnet-FAST III,因为 QNX 6.5 里对应的devn-pcnet驱动兼容性更老成,识别率更高。
配置的命令是:
io-net -d pcnet -p tcpip ifconfig en0 192.168.56.10 netmask 255.255.255.0 up route add default 192.168.56.1QNX 里网卡设备名固定是en0。如果要走 DHCP,把 ifconfig 那两行换掉,运行:
dhcp.client -i en0 &配完用ifconfig en0看一下状态,再用ping试一下宿主机。注意 VirtualBox 的网络模式要选对:NAT 模式下虚拟机可以出去,但宿主机访问不了它;桥接模式下虚拟机在局域网里有独立 IP,方便双向访问;**仅主机模式(Host-Only)**最干净,适合纯内网调试。我做嵌入式开发一般用 Host-Only 加一块 NAT 网卡,一个跑调试,一个用来下载包。
4.2 分辨率与 crttrap
分辨率这事在上一节提了 crttrap,这里补充几个实际会遇到的情况。
第一种,探测出来只有 640x480 和 800x600,没有 1024x768。原因是 VBE 模式表里没有更大的模式,用刚才那条setextradata加一个自定义模式就好。注意模式字符串的格式必须是宽x高x色深,色深写 32 而不是 24,因为 QNX 的 vesabios 驱动在某些版本上对 24 位模式处理有问题。
第二种,进了桌面但鼠标是个静止的方块。这是鼠标驱动没加载。QNX 6.5 用devi-hirun管理输入设备,命令是:
devi-hirun ps2 msoftVirtualBox 模拟的是 PS/2 鼠标,用这个参数就行。这一步建议写进启动脚本,免得每次手动敲。
第三种,桌面起了但窗口一拖动就花屏。这是显存不够,回去把显存从默认的 8MB 调到 32MB。Photon 的双缓冲机制对显存有要求。
4.3 宿主机与 QNX 之间传文件
这一块是新手最容易卡住的地方。VirtualBox 的"共享文件夹"功能依赖 Guest Additions,而 QNX 根本没有 Guest Additions,所以从菜单里加共享文件夹是一条死路。我给几种实际可用的办法,按推荐度排序。
办法一:FTP。QNX 6.5 自带 FTP 服务端和客户端。在 QNX 里起服务端:
ftpd &然后在宿主机用任意 FTP 客户端连到虚拟机的 IP,用 root 登录就能上传下载。这个方案零配置,我日常用得最多。
办法二:挂载 Windows 共享(fs-cifs)。这是 QNX 的一个隐藏技能,它的文件系统层里有 CIFS 客户端,可以把宿主机的共享目录挂成本地目录:
mount -T cifs //192.168.56.1/share /mnt/share -u 用户名 -P 密码挂上之后就和本地目录一样,cp、ls都能用。缺点是 QNX 6.5 的 CIFS 实现比较老,只支持 SMB1 协议,如果你的宿主机是新版 Windows,需要在共享设置里手动开启 SMB1 支持。Linux 宿主机上跑 Samba 同理,要允许 SMB1。
办法三:挂第二块磁盘或 ISO。用 VBoxManage 在 IDE 上再挂一个 FAT 格式的 VDI,在 QNX 里用mount -tdos /dev/hd1t77 /mnt/dos挂载。适合一次性传大批文件,但不适合频繁交换。
办法四:HTTP。宿主机跑一个简单的 HTTP 服务(Python 一行命令就够),QNX 里用ftp客户端或者curl去拉。QNX 6.5 默认不带 wget,需要自己编译或者找现成的包。
注意:QNX 6.5 的文件权限模型和 Linux 基本一致,但从 FTP 上传的文件默认权限可能不对,可执行文件要手动
chmod +x,否则运行时报"权限不足",这个报错很容易被误判成二进制格式问题。
5. 常见故障与排查实录
装机过程中我遇到过的问题,按发生位置分两类:VirtualBox 侧的和 QNX 侧的。分开看会快很多。
5.1 VirtualBox 侧:rc=-1908 与驱动加载失败
错误码rc=-1908是最经典的一个,完整信息是 "The VirtualBox Linux kernel driver is either not loaded or not set up correctly"。它不是虚拟机的问题,是宿主机的问题——VirtualBox 需要的内核模块没编译或者没加载。
Linux 宿主机的排查顺序是这样:先看lsmod | grep vbox有没有输出,没有就手动modprobe vboxdrv,如果 modprobe 报错,说明模块压根没编译成功。这时候执行sudo /sbin/vboxconfig重新编译。编译失败最常见的原因是内核头文件没装,Debian 系装linux-headers-$(uname -r),红帽系装kernel-devel。还有一个坑是Secure Boot:开着 Secure Boot 的内核拒绝加载未签名的第三方模块,表现和编译失败几乎一样,但日志里会明确写 "module verification failed"。解决方式是在 BIOS 里关掉 Secure Boot,或者给模块签名。
Windows 宿主机上的"无法在此设备上加载驱动程序",通常和 Hyper-V 有关。Windows 开启 Hyper-V 或 WSL2 之后,VirtualBox 只能以 Hyper-V 兼容后端运行,性能会掉一大截,某些老 guest 系统还会直接起不来。我的做法是开发嵌入式时把 Hyper-V、WSL2、内存完整性(HVCI)这几个功能临时关掉,用完之后再开。这个切换需要重启,比较烦,所以很多人专门留一台机器或者用双系统。
5.2 QNX 侧:找不到设备、起不来图形
QNX 侧的故障有一个共同特点:问题都写在启动过程的滚动日志里,只是刷得太快。我建议装完之后第一件事是学会看日志。QNX 的启动信息可以用dmesg查看,或者直接读/proc下的信息。
症状一:启动卡在 "Waiting for devb-eide"。说明块设备驱动没能挂上硬盘。回去检查 IDE 控制器配置、硬盘是否挂在主通道、虚拟机的 EFI 是否关闭。
症状二:进了系统但pci命令看不到网卡。QNX 6.5 的pci工具可以列出 PCI 总线上的所有设备。如果网卡不在这里,是 VirtualBox 层面没挂上;如果在这里但io-net加载失败,是驱动模块选错了。用pci -v可以看到设备的 vendor ID 和 device ID,比如 e1000 是 8086:100E,pcnet 是 1022:2000,对着 ID 选驱动就不会错。
症状三:Photon 起不来,报 "no graphics driver found"。检查 crttrap 的配置文件在不在,以及 io-graphics 有没有启动。可以在文本模式下先跑io-graphics -d vesabios手动加载,看它报什么错。
症状四:系统能起但特别慢,像在爬。大概率是内存给少了,系统在疯狂换页。QNX 6.5 在 256MB 以下运行时,Photon 和编译工具同时开着会非常难受。
5.3 排查速查表
我把上面这些问题整理成一张表,方便你对着症状找方向。
| 现象 | 最可能的原因 | 排查命令 / 动作 |
|---|---|---|
| 安装向导找不到磁盘 | 存储控制器不是 IDE / 开了 EFI | 检查存储设置与系统设置 |
| 启动后又回到安装界面 | ISO 没弹出,从光盘重启 | 存储设置里把光驱指向"空" |
| rc=-1908 | 宿主机内核模块未编译或未加载 | modprobe vboxdrv、vboxconfig、装内核头文件 |
| 图形界面起不来 | 图形控制器选了 VMSVGA | 改成 VBoxSVGA 或 VBoxVGA |
| 分辨率只有 640x480 | VBE 模式表缺大分辨率 | 加 CustomVideoMode,重跑 crttrap |
| 鼠标不动 | devi-hirun 没加载 | devi-hirun ps2 msoft |
| 网络不通 | 驱动模块与网卡型号不匹配 | pci -v看设备 ID,换驱动 |
| 磁盘有空间但建不了文件 | inode 耗尽 | 重做文件系统,加大 inode 数量 |
| 密码输对了登不进去 | 密码超过 8 位被截断 | 用 8 位以内密码 |
| 上传的可执行文件跑不了 | 权限位不对 | chmod +x |
6. 从跑起来到用得顺手
装完能用只是及格线。这一节讲三个能让 QNX 用起来更顺手的方向,都是我在实际项目里反复用到的。
6.1 开机自启动脚本怎么放
QNX 的启动流程和 Linux 的 systemd 完全不是一回事。它启动时执行的是/etc/system/sysinit这个脚本,然后由这个脚本去拉起各个服务。如果你想让某个程序开机自动跑,有两种做法。
第一种,直接改/etc/system/sysinit,在文件末尾加你的启动命令,记得加&放到后台,否则会阻塞启动流程。这种做法适合简单场景,但缺点是升级系统时容易被覆盖。
第二种,更规范的做法是看系统有没有加载/etc/rc.d/rc.local,很多 QNX 发行配置里会留这么一个钩子,专门给用户放自定义启动项。你可以把网卡配置、鼠标加载、自己的应用启动都写进去:
# 网卡 io-net -d pcnet -p tcpip & sleep 2 ifconfig en0 192.168.56.10 netmask 255.255.255.0 up route add default 192.168.56.1 # 鼠标 devi-hirun ps2 msoft & # 自己的应用 /home/user/myapp &有个细节要注意:io-net加载到协议栈可用之间有延迟,所以后面的 ifconfig 最好加个 sleep,否则会报"设备不存在",然后过两秒你再手动跑一次就好了。这种时序问题在嵌入式启动脚本里非常常见,加 sleep 是最土但最有效的办法。
6.2 用 mkifs 裁剪自己的启动镜像
QNX 有个很强的能力:整个系统可以从一个定制的启动镜像跑起来,这个镜像只有几 MB,包含内核、启动脚本和必要的驱动。做这个事需要写一个build file,然后用mkifs工具编译成.ifs文件。
build file 的语法大概是这样的结构:
[image=0x80000] [virtual=x86,bios] .bootstrap = { startup-bios -D 0x1000 PATH=/proc/boot procnto } [+script] .script = { devb-eide blk cache=1m dos exfat qnx6 & io-net -d pcnet -p tcpip & waitfor /dev/io-net/en0 4 ifconfig en0 192.168.56.10 up } [type=link] /dev/console = /dev/ser1方括号里是属性段,image是加载地址,virtual声明目标平台,.bootstrap是引导部分,.script是启动后执行的脚本。[+script]里的waitfor就是专门解决刚才说的时序问题的,比 sleep 优雅。
编译命令:
mkifs -v mybuild.build myimage.ifs生成的.ifs文件可以配一个 IPL 写到引导扇区,也可以在 VirtualBox 里直接当软盘或硬盘镜像启动。这个过程我第一次做的时候摔了好几跤,主要坑在两处:一是startup-bios后面的参数要和你的硬件匹配,写错了起不来还看不到任何报错;二是 build file 里的路径都是相对于/proc/boot的,写成绝对路径会找不到文件。
6.3 qconn 与远程调试
QNX 有一个叫qconn的守护进程,是官方 IDE(Momentics)和 Eclipse 插件连接目标机用的。跑起来之后,宿主机上的 IDE 可以远程查看进程列表、线程状态、内存使用,还能在线程级别下断点、看调用栈。这是 QNX 相比裸机开发最爽的一点。
开启方式:
qconn &默认监听 8000 端口。宿主机 IDE 里新建一个 QNX 目标连接,填虚拟机 IP,就能连上。连上之后你会发现pidin里的那些信息在 IDE 里有可视化界面,调一个多线程的实时程序,能直接看到每个线程的优先级、状态切换和 CPU 占用时间,定位抖动问题非常直观。
USB 这块补充一句:VirtualBox 装了扩展包之后可以做 USB 直通,把宿主机上的 USB 转串口线或者调试器直接映射进虚拟机。做底层驱动开发时,这个能力可以让你在虚拟机里调试真实外设,省得为了测试专门买一台工控机。
7. 最后聊聊我的实际体会
虚拟机里跑 QNX 这件事,最大的价值不是"省钱",而是给你一个可以随时推倒重来的沙盒。微内核的架构、用户态驱动的隔离、优先级调度的效果,这些东西光看文档是体会不到的。你得自己把网卡驱动杀掉一次、看着系统该怎么跑还怎么跑,才能真正理解 QNX 的设计哲学。
我个人的习惯是常备三个 QNX 虚拟机:一个纯文本的最小系统,专门用来试 build file 和启动脚本;一个带 Photon 的完整系统,用来跑图形应用和验证驱动;还有一个用来折腾新版本的 BSP。快照功能在这里帮了大忙,装好一个干净的基线之后立刻快照,后面无论怎么折腾,五分钟就能回到出厂状态。
如果你装完之后发现自己卡在某个具体环节,最快的排查路径永远是回到文本控制台,用pidin ar看进程、用use -l看设备、用dmesg看日志。QNX 的系统信息暴露得非常彻底,几乎所有问题都能从这三个命令里找到线索——这一点比很多把错误信息藏在层层抽象里的系统要友好得多。