零基础交叉编译实战:HelloWorld程序编译与板端运行
作者:黒漂技术佬
适合人群:刚配好交叉工具链的嵌入式新手
关键词:HelloWorld、交叉编译、开发板运行、文件传输
引言
理论看了一堆,工具链也装了,现在到了最激动人心的环节——亲自动手编译一个程序,传到开发板上跑起来!别小看这个 HelloWorld,它打通了"写代码→交叉编译→传输→运行"的完整链路。走通这一遍,你就算真正入了嵌入式的门。
一、编写HelloWorld程序
1.1 创建源文件
在你的开发主机上创建一个工作目录,写一个稍微"有点料"的 HelloWorld:
# 创建工作目录mkdir-p~/embedded_projects/hellocd~/embedded_projects/hello# 创建源文件vimhello.c1.2 源码内容
不要只写一行printf,加一点信息让程序在板端运行时更有参考价值:
#include<stdio.h>#include<string.h>#include<time.h>intmain(intargc,char*argv[]){printf("========================================\n");printf(" Hello Embedded World!\n");printf(" 交叉编译测试程序\n");printf("========================================\n");/* 打印参数信息 */if(argc>1){printf("输入参数: ");for(inti=1;i<argc;i++){printf("%s ",argv[i]);}printf("\n");}/* 打印当前时间,验证time库能正常工作 */time_tt;structtm*tm_info;time(&t);tm_info=localtime(&t);printf("当前时间: %s",asctime(tm_info));/* 字符串操作,验证string库 */charboard[]="ARM Linux Board";printf("运行平台: %s (长度: %lu)\n",board,strlen(board));printf("========================================\n");printf(" 程序执行成功!\n");printf("========================================\n");return0;}这个程序涉及printf、时间获取、字符串操作,能验证 C 标准库是否正常链接,比单纯输出一句话更有诊断价值。
二、交叉编译
2.1 基本编译
确保你的交叉工具链已经配置好(上一篇的内容),然后执行编译:
# 使用交叉编译器编译arm-linux-gnueabihf-gcc hello.c-ohello_arm# 如果没有配置环境变量,需要写完整路径# /opt/gcc-linaro-7.5.0/bin/arm-linux-gnueabihf-gcc hello.c -o hello_arm2.2 验证编译产物
编译完成后,先验证生成的可执行文件架构是否正确:
# 查看文件类型filehello_arm预期输出:
hello_arm: ELF 32-bit LSB executable, ARM, EABI5, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped关键信息解读:
| 字段 | 含义 | 说明 |
|---|---|---|
| ELF 32-bit | 32位可执行文件 | ARM 32位架构 |
| LSB | Little Endian | 小端字节序 |
| ARM | 目标架构 | ARM指令集 |
| EABI5 | 嵌入式ABI版本5 | 接口标准 |
| dynamically linked | 动态链接 | 运行时需要C库 |
| interpreter /lib/ld-linux-armhf.so.3 | 动态链接器路径 | 目标板上必须有此文件 |
2.3 静态编译(备选方案)
如果你的开发板上没有对应的 C 库(libc.so等),动态链接的程序会运行失败。这时可以静态编译:
# 静态链接,把C库打包进可执行文件arm-linux-gnueabihf-gcc hello.c-ohello_arm_static-static# 查看文件大小对比ls-lhhello_arm hello_arm_static输出对比:
-rwxr-xr-x 1 user user 6.4K hello_arm # 动态链接,体积小 -rwxr-xr-x 1 user user 728K hello_arm_static # 静态链接,体积大静态编译的文件大很多(因为把整个C库塞进去了),但好处是放到任何ARM板上都能跑,不依赖目标板的库版本。
2.4 开启调试信息
后续可能需要用GDB调试,编译时加上-g参数:
arm-linux-gnueabihf-gcc-ghello.c-ohello_arm_debug三、传输到开发板
编译好的程序在PC上跑不了(架构不同),需要传到ARM开发板上。这里先用最通用的方式——通过U盘拷贝或网络传输。
3.1 方式一:U盘拷贝(最简单)
# PC上拷贝到U盘cphello_arm /media/youruser/Udisk/# U盘插到开发板上,自动挂载后# 在开发板终端执行:cp/mnt/udisk/hello_arm ~/chmod+x ~/hello_arm3.2 方式二:串口传输(无网络时适用)
如果开发板没有网络,可以用rz/sz工具通过串口传输:
# 开发板上需要安装 lrzszopkginstalllrzsz# 或 apt install lrzsz# 开发板终端执行rz# 然后在串口工具(如MobaXterm)中选择文件发送3.3 方式三:SCP网络传输(最常用)
开发板和PC在同一网络中时,用SCP最方便:
# 从PC传到开发板(假设开发板IP为192.168.1.100)scphello_arm root@192.168.1.100:/root/# 开发板需已开启SSH服务SCP的详细配置和使用方法会在后续文章中专门讲解,这里先用起来。
四、板端运行验证
4.1 SSH/串口连接开发板
# 通过SSH连接开发板sshroot@192.168.1.100# 或通过串口连接(需用串口工具)# MobaXterm / minicom / picocom 均可4.2 运行程序
# 进入程序所在目录cd/root# 赋予执行权限(如果还没有的话)chmod+x hello_arm# 运行./hello_arm4.3 预期输出
======================================== Hello Embedded World! 交叉编译测试程序 ======================================== 当前时间: Fri Jul 10 14:23:56 2026 运行平台: ARM Linux Board (长度: 15) ======================================== 程序执行成功! ========================================看到这行输出,恭喜你——交叉编译全链路打通了!
4.4 带参数运行
./hello_arm arg1 arg2输出中会额外显示:
输入参数: arg1 arg2五、常见问题排查
5.1 Permission denied
# 报错:./hello_arm: Permission denied# 原因:文件没有执行权限# 解决:chmod+x hello_arm5.2 No such file or directory
# 报错:./hello_arm: No such file or directory# 原因:文件确实存在,但动态链接器找不到# 排查:file./hello_arm# 查看interpreter路径ls/lib/ld-linux-armhf.so.3# 检查开发板上是否有此文件# 解决方案一:安装缺失的库aptinstalllibc6# 或对应的包# 解决方案二:使用静态编译版本./hello_arm_static5.3 cannot execute binary file
# 报错:./hello_arm: cannot execute binary file: Exec format error# 原因:架构不匹配(可能用了x86编译或ARM64编译的文件)# 排查:file./hello_arm# 如果显示 x86-64 而非 ARM,说明用错了编译器# 解决:用正确的交叉编译器重新编译问题速查表
| 报错信息 | 根本原因 | 解决方案 |
|---|---|---|
| Permission denied | 无执行权限 | chmod +x |
| No such file or directory | 缺动态链接器 | 静态编译或安装C库 |
| cannot execute binary file | 架构不匹配 | 用正确的交叉编译器 |
| Segmentation fault | ABI不兼容 | 检查hf/非hf工具链 |
总结
从编写源码到交叉编译、传输、板端运行,这四步构成了嵌入式开发的日常循环。HelloWorld虽然简单,但它验证了整个工具链的正确性:编译器能工作、C库能链接、传输通道畅通、开发板运行时库完整。动态编译体积小但依赖目标板库,静态编译体积大但移植性强,开发阶段常用动态编译方便调试。运行时遇到报错别慌,用file命令查看文件信息是排查的第一步。这条链路跑通了,后面编译复杂项目就是在此基础上叠加Makefile和依赖管理的事了。