第2章:开发环境搭建

好,咱们正式开始动手了。这一章我带你把开发环境搭起来。说实话,QNX的开发环境搭建,比Linux要繁琐一些,但也没那么玄乎。我当年第一次接触QNX时,光配交叉编译链就折腾了一下午。现在回想起来,其实就是几个关键点没搞明白。

2.1 QNX Momentics IDE安装

QNX Momentics IDE,说白了就是一套基于Eclipse的集成开发环境。QNX官方把它打包好了,你直接装就行。我个人习惯用7.0或7.1版本,这两个版本比较稳定。

安装步骤:

  1. 从QNX官网下载Momentics IDE安装包(需要注册账号)
  2. 运行安装程序,选择安装路径(建议不要有中文和空格)
  3. 选择组件:至少勾选“QNX SDK”和“Target Support”
  4. 等待安装完成,大概10-15分钟

嗯,这里要注意:安装路径别太深。我曾经把QNX装在一个很深的目录下,结果编译时路径超长报错,排查了半天才发现是这个问题。

2.2 QNX SDK配置

SDK配置是重头戏。QNX的SDK包含了头文件、库文件、以及最重要的——系统镜像。你想想看,没有SDK,你连printf都调不了。

配置SDK其实就两步:

  1. 设置环境变量:主要是QNX_HOST和QNX_TARGET
  2. 导入SDK到IDE:在Momentics里通过Preferences -> QNX -> SDK Manager导入

我建议你直接在.bashrc或.profile里加上这几行:

export QNX_HOST=/opt/qnx710/host/linux/x86_64
export QNX_TARGET=/opt/qnx710/target/qnx7
export PATH=$QNX_HOST/usr/bin:$PATH
export MAKEFLAGS=-j4

为什么要加MAKEFLAGS?因为QNX的make默认单线程编译,加上-j4能快不少。我在项目中遇到过,不加这个参数,编译一个稍大的工程要等好几分钟。

2.3 交叉编译工具链

交叉编译,说白了就是在你的PC上编译出能在ARM或x86目标板上运行的代码。QNX的工具链命名很直观:

目标架构 编译器名称 常见用途
ARMv7 arm-unknown-nto-qnx7.0.0eabi-gcc i.MX6、AM335x等
ARMv8 (AArch64) aarch64-unknown-nto-qnx7.0.0-gcc 树莓派3/4、i.MX8
x86_64 x86_64-pc-nto-qnx7.0.0-gcc QNX虚拟机、x86工控机

怎么验证工具链是否可用?我一般写个最简单的hello world:

#include <stdio.h>
int main() {
    printf("Hello from QNX!\n");
    return 0;
}

然后用交叉编译器编译:

aarch64-unknown-nto-qnx7.0.0-gcc -o hello hello.c

如果没报错,生成了hello文件,那就说明工具链没问题。我曾经犯过一个低级错误——用错了编译器版本,编译出来的程序在目标机上跑不起来,报“Invalid ELF header”。后来才发现,目标机是ARMv7,我用了ARMv8的编译器。

避坑指南:一定要确认目标机的架构。用file命令查看编译出的二进制文件:

file hello
# 输出示例:ELF 64-bit LSB executable, ARM aarch64, ...

2.4 目标机与宿主机连接

环境搭好了,怎么把程序跑起来?你需要让宿主机(你的PC)和目标机(开发板)能通信。常用的方式有两种:

  • 串口连接:调试内核、看启动日志时用
  • 网络连接:传输文件、远程调试时用

我个人更推荐网络连接,速度快,还能用ssh。配置网络连接时,你需要知道目标机的IP地址。怎么获取?

  1. 用串口连上目标机,登录后执行ifconfig
  2. 或者,在QNX启动时,串口输出里会打印IP地址

拿到IP后,在宿主机上测试连通性:

ping 192.168.1.100

通了之后,就可以用QNX的qconn服务来远程调试了。在Momentics IDE里,新建一个QNX Target,填上IP地址和端口(默认8000),IDE就能自动识别目标机。

小技巧:如果网络不通,先检查防火墙。我遇到过好几次,Windows防火墙把QNX的端口给拦了。把8000端口放行就好了。

2.5 验证环境

最后一步,验证整个环境是否正常工作。我习惯写一个简单的多线程程序来测试:

#include <stdio.h>
#include <pthread.h>

void* thread_func(void* arg) {
    printf("Thread running on QNX!\n");
    return NULL;
}

int main() {
    pthread_t tid;
    pthread_create(&tid, NULL, thread_func, NULL);
    pthread_join(tid, NULL);
    printf("Main done.\n");
    return 0;
}

编译后传到目标机上运行。如果能看到两行输出,恭喜你,环境搭建成功了!

嗯,这一章的内容就这些。环境搭建虽然繁琐,但一次配好,后面就省心了。下一章我们开始讲QNX的进程管理,那才是真正有意思的部分。