1. 为什么要在嵌入式Linux上移植adb/adbd?

在嵌入式开发中,我们经常需要在PC和开发板之间传输文件。传统的FTP、SCP等方式虽然能用,但操作起来总是不够直观方便。Android的adb工具链就完美解决了这个问题 - 它不仅能实现文件传输,还支持shell访问、端口转发等高级功能。

我最近在一个ARM架构的工控板项目上就遇到了这个需求。客户要求通过USB线直接管理设备文件,adb的push/pull功能正好符合要求。但问题是这个板子跑的是标准Linux系统,不是Android。经过一番折腾,我成功交叉编译了adb/adbd工具链,现在分享下完整过程。

2. 环境准备与依赖库编译

2.1 搭建交叉编译环境

我用的宿主机是Ubuntu 20.04,目标板是Cortex-A53架构。首先需要安装合适的交叉编译器:

sudo apt install gcc-arm-linux-gnueabihf

验证编译器是否正常工作:

arm-linux-gnueabihf-gcc -v

如果显示类似"Target: arm-linux-gnueabihf"的输出,说明环境就绪。对于其他架构的开发板,可能需要从芯片厂商获取专用工具链。

2.2 交叉编译zlib库

adb依赖zlib进行数据压缩,我们先编译它:

wget https://zlib.net/zlib-1.2.11.tar.gz
tar xvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
CC=arm-linux-gnueabihf-gcc ./configure --prefix=$PWD/../zlib-arm
make -j$(nproc)
make install

这里有几个关键点:

  • CC指定交叉编译器
  • --prefix设置安装目录
  • 编译完成后会在上级目录生成zlib-arm文件夹

2.3 交叉编译OpenSSL

adb的加密通信需要OpenSSL支持:

wget https://www.openssl.org/source/openssl-1.1.1.tar.gz
tar xvf openssl-1.1.1.tar.gz
cd openssl-1.1.1
./Configure linux-armv4 shared --cross-compile-prefix=arm-linux-gnueabihf- --prefix=$PWD/../openssl-arm
make -j$(nproc)
make install

注意参数说明:

  • linux-armv4指定目标平台
  • shared生成动态库
  • --cross-compile-prefix设置工具链前缀
  • 同样会在上级目录生成openssl-arm文件夹

3. 修改Android-tools源码

3.1 获取源码并准备编译环境

我使用的是android-tools-4.2.2版本:

git clone https://github.com/android/platform_system_core.git
cd platform_system_core/adb

需要将debian目录下的mk文件复制到对应位置:

cp debian/makefiles/adbd.mk Makefile

3.2 关键Makefile修改

主要修改点包括:

  1. 替换交叉编译器路径
  2. 添加依赖库的头文件和库路径
  3. 调整编译选项

修改后的Makefile关键部分:

CC := arm-linux-gnueabihf-gcc
CPPFLAGS += -I/path/to/zlib-arm/include
CPPFLAGS += -I/path/to/openssl-arm/include
LDFLAGS += -L/path/to/zlib-arm/lib
LDFLAGS += -L/path/to/openssl-arm/lib
LIBS += -lz -lcrypto

特别要注意的是需要添加-DADBD_NON_ANDROID宏定义,告诉代码这是运行在非Android环境。

4. 编译与部署

4.1 执行编译

在adb目录下直接运行:

make clean
make -j$(nproc)

如果一切顺利,会生成adbd可执行文件。可以用file命令验证:

file adbd
# 应该显示:adbd: ELF 32-bit LSB executable, ARM...

4.2 部署到开发板

将生成的文件和依赖库拷贝到开发板:

scp adbd root@192.168.1.100:/usr/bin
scp /path/to/zlib-arm/lib/libz.so.* root@192.168.1.100:/usr/lib
scp /path/to/openssl-arm/lib/libcrypto.so.* root@192.168.1.100:/usr/lib

在开发板上设置环境变量并启动服务:

export LD_LIBRARY_PATH=/usr/lib
adbd &

4.3 PC端连接测试

在PC上安装adb工具后:

adb connect 192.168.1.100
adb devices
# 应该能看到设备列表
adb shell
# 可以进入交互式shell

5. 常见问题排查

5.1 设备无法识别

如果adb devices看不到设备,可以尝试:

  1. 检查USB连接是否正常
  2. 开发板是否开启了USB调试模式
  3. 在PC上添加udev规则:
sudo tee /etc/udev/rules.d/51-android.rules <<EOF
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666"
EOF
sudo udevadm control --reload

5.2 库文件缺失错误

如果运行时提示缺少so文件,可以用ldd检查依赖:

ldd adbd

将缺失的库文件拷贝到开发板的/lib或/usr/lib目录。

5.3 版本兼容性问题

不同版本的adb/adbd可能存在协议不兼容。建议保持PC端adb工具和开发板adbd版本一致。可以通过编译参数指定协议版本:

CPPFLAGS += -DADB_VERSION="1.0.32"

6. 进阶配置与优化

6.1 设置adbd为系统服务

为了让adbd开机自启,可以创建systemd服务:

cat > /etc/systemd/system/adbd.service <<EOF
[Unit]
Description=ADB Daemon
After=network.target

[Service]
ExecStart=/usr/bin/adbd
Restart=always

[Install]
WantedBy=multi-user.target
EOF

systemctl enable adbd
systemctl start adbd

6.2 启用加密连接

默认情况下adb通信是不加密的。要启用TLS加密:

  1. 在开发板生成密钥:
openssl genrsa -out adbkey 2048
openssl rsa -in adbkey -pubout -out adbkey.pub
  1. 将公钥拷贝到PC的~/.android/adbkey.pub

  2. 重新编译adbd时添加加密支持:

CPPFLAGS += -DALLOW_ADBD_AUTH=1

6.3 性能优化建议

对于资源受限的设备,可以调整以下参数:

  1. 减小缓冲区大小:
CPPFLAGS += -DADB_BUFFER_SIZE=4096
  1. 禁用不必要功能:
CPPFLAGS += -DNO_SERVICES=1
  1. 使用静态链接减少依赖:
LDFLAGS += -static

7. 实际应用案例

在我最近的一个智能家居网关项目中,就成功应用了这套方案。网关采用Rockchip RK3308芯片,运行Buildroot构建的Linux系统。通过移植adbd,实现了:

  • 开发阶段快速部署应用
  • 生产环境远程日志收集
  • 现场问题诊断与修复

一个特别实用的技巧是结合adb over WiFi:

  1. 先用USB线连接并执行:
adb tcpip 5555
  1. 拔掉USB线后仍可通过网络连接:
adb connect 192.168.1.100:5555

这大大提高了现场调试的效率。整个移植过程最耗时的部分是解决库依赖问题,特别是不同版本OpenSSL的兼容性。建议在项目初期就确定好各组件版本,避免后期调整带来的额外工作量。

更多推荐