结论速览
- 头文件和 libc 里有声明只说明 API 存在,不代表 Kernel 支持该功能;能编译不等于运行时可用。
- 网络功能要 Kernel 打开
CONFIG_NET、CONFIG_INET,还要有 MT7621 Ethernet Driver、MDIO、PHY Driver,链上任何一层缺失都不通。 /dev/ttyS0需要 serial core、UART driver、设备树匹配、设备节点齐备才会出现。- rootfs 用 ext4、UBIFS 还是别的格式,Kernel 必须对应支持,否则无法挂载。
- 常见启动问题未必是驱动代码有错,更多是 DTS 地址、中断、时钟、compatible 不匹配或
status = "disabled"。 - 应用功能失败时按「应用 API、libc、Kernel 功能、驱动、设备树、硬件」逐层排查,比直接怀疑应用代码高效。
1. 能编译不等于运行时可用
例如应用代码:
1 | socket(AF_INET, SOCK_STREAM, 0); |
只要工具链的头文件和 libc 有对应声明,就可能编译成功。
但如果 Kernel 没有网络功能,运行时仍然失败。
所以:
1 | 用户空间 API 存在 |
2. Kernel 配置决定功能
例如网络功能通常涉及:
1 | CONFIG_NET |
如果需要网卡,还要有:
1 | MT7621 Ethernet Driver |
完整链:
1 | App |
其中任何一层缺失,都可能导致网络不可用。
3. /dev/ttyS0 也不是凭空出现
应用:
1 | open("/dev/ttyS0", O_RDWR); |
要正常使用,还需要:
1 | Kernel serial core |
所以 open() 能编译只是说明 API 存在。
并不说明具体设备一定存在。
4. 文件系统也需要 Kernel 支持
如果 rootfs 是 ext4:
1 | Kernel |
如果使用 UBIFS:
1 | Kernel |
如果 rootfs 格式内核不认识,就无法挂载。
5. 驱动和设备树的关系
对于很多 SoC 外设:
1 | 设备树 |
所以常见启动问题可能并不是驱动代码有错,而是:
1 | DTS 地址错误 |
6. 分析原则
当应用功能失败时,按层排查:
1 | 应用 API 是否正确 |
这样比直接怀疑应用代码高效得多。