1. 搭建QNX驱动开发环境
任务目标
在虚拟机中完成QNX SDP 7.0的安装,配置宿主机与QNX虚拟机之间的交叉编译链路,创建最小字符设备驱动项目并成功编译生成可加载的.so驱动文件。
环境与依赖
- 宿主机:Ubuntu 20.04/22.04 x86_64,已安装VirtualBox 6.1+或VMware Workstation 15+
- 虚拟机:QNX SDP 7.0(含QNX Neutrino 7.0实时操作系统),镜像文件
qnx-sdp-7.0-desktop.iso - 交叉编译工具链:QNX SDP自带的
qcc(基于GCC的QNX交叉编译器),安装后位于$QNX_HOST/usr/bin/qcc - 目标架构:x86_64(虚拟机架构),编译时使用
-Vgcc_ntox86_64选项指定
实施步骤
1. 虚拟机安装QNX SDP
- 在VirtualBox中新建虚拟机,类型选择
Other/Unknown(64位),分配至少4GB内存、40GB动态扩展虚拟硬盘。 - 挂载
qnx-sdp-7.0-desktop.iso启动,按提示完成安装。安装时选择QNX Neutrino Desktop图形环境。 - 安装完成后进入系统,打开终端确认版本:
uname -a应显示QNX与x86_64。
2. 配置网络与共享目录
- 虚拟机网络设为
桥接模式,确保宿主机与虚拟机可互相ping通。 - 在宿主机创建共享目录
~/qnx_share,通过VirtualBox共享文件夹或Samba挂载到虚拟机/data目录,用于传输源码与编译产物。
3. 配置交叉编译环境
在宿主机安装QNX SDP主机端工具(Host部分),安装完成后设置环境变量:
export QNX_TARGET=/opt/qnx700/target/qnx7
export QNX_HOST=/opt/qnx700/host/linux/x86_64
export PATH=$QNX_HOST/usr/bin:$PATH
验证工具链可用:
qcc -Vgcc_ntox86_64 --version
输出应显示QNX编译器版本信息,说明交叉编译工具链配置成功。
4. 创建最小驱动项目
在宿主机~/qnx_share下创建驱动项目目录minidrv,包含以下文件:
项目文件:minidrv/build.sh
#!/bin/sh
# QNX最小驱动编译脚本
export QNX_TARGET=/opt/qnx700/target/qnx7
export QNX_HOST=/opt/qnx700/host/linux/x86_64
export PATH=$QNX_HOST/usr/bin:$PATH
qcc -Vgcc_ntox86_64 -c minidrv.c -o minidrv.o
qcc -Vgcc_ntox86_64 -shared -o minidrv.so minidrv.o
echo "Build complete: minidrv.so"
驱动源码:minidrv/minidrv.c
#include <sys/types.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <stdio.h>
#include <string.h>
// 驱动名称与版本
static char *drv_name = "minidrv";
static char *drv_version = "1.0.0";
// 设备路径名
static char *dev_path = "/dev/minidrv";
// 连接处理函数
static int io_open(resmgr_context_t *ctp, io_open_t *msg, void *extra) {
return iofunc_open_default(ctp, msg, NULL, NULL);
}
// 设备关闭处理
static int io_close(resmgr_context_t *ctp, void *reserved, void *extra) {
return iofunc_close_default(ctp, reserved, NULL);
}
// 设备读取处理
static int io_read(resmgr_context_t *ctp, io_read_t *msg, void *extra) {
char buf[] = "minidrv: hello from QNX driver\n";
int len = strlen(buf);
if (msg->nbytes > len) {
msg->nbytes = len;
}
return resmgr_handler(ctp, buf, msg->nbytes);
}
int main(int argc, char **argv) {
dispatch_t *dpp;
resmgr_attr_t resmgr_attr;
dispatch_context_t *ctp;
int id;
// 初始化dispatch
dpp = dispatch_create();
if (dpp == NULL) {
fprintf(stderr, "Failed to create dispatch\n");
return 1;
}
// 初始化资源管理器属性
memset(&resmgr_attr, 0, sizeof(resmgr_attr));
resmgr_attr.nparts = 1;
resmgr_attr.handle = NULL;
// 注册资源管理器
id = resmgr_attach(dpp, &resmgr_attr, dev_path,
_FTYPE_ANY, 0, NULL, NULL);
if (id == -1) {
fprintf(stderr, "Failed to attach resource manager\n");
return 1;
}
// 创建dispatch上下文
ctp = dispatch_context_alloc(dpp);
if (ctp == NULL) {
fprintf(stderr, "Failed to allocate dispatch context\n");
return 1;
}
printf("%s v%s started, device at %s\n",
drv_name, drv_version, dev_path);
// 主循环处理消息
while (1) {
if (dispatch_block(ctp) == -1) {
fprintf(stderr, "dispatch_block failed\n");
break;
}
dispatch_handler(ctp);
}
// 清理
resmgr_detach(dpp, id, NULL);
dispatch_context_free(ctp);
dispatch_destroy(dpp);
return 0;
}
5. 编译与部署
- 在宿主机执行:
chmod +x build.sh && ./build.sh - 编译成功后,将
minidrv.so复制到虚拟机/data目录。 - 在虚拟机中执行:
cp /data/minidrv.so /lib/modules/(或直接运行mount -T io-pkt /lib/modules/minidrv.so加载)。
验证方法
- 编译验证:build.sh执行无报错,生成
minidrv.so文件。 - 加载验证:在QNX虚拟机中执行
mount -T io-pkt /lib/modules/minidrv.so,无错误输出。 - 功能验证:执行
cat /dev/minidrv,预期输出:minidrv: hello from QNX driver。 - 卸载验证:执行
umount /dev/minidrv,确认设备节点消失。
以上步骤全部通过,即完成QNX驱动开发环境搭建与最小驱动编译验证闭环。