ADB的底层原理

一、PC 侧 adb server

我们在终端敲的 adb 命令,第一步不是直接发给板子,而是发给本机 adb server 的 127.0.0.1:5037。

1、adb server 是一个 TCP 服务端,持续监听 5037。

2、adb client(短进程)作为 TCP 客户端连接 5037,发送控制命令(文本格式,不是标准 adb 数据流包)

3、client 发给 server 的控制指令 例子

复制代码
host:devices
host:transport:xxxxxx
host:shell
host:forward:tcp:8888;tcp:8888
  • host: 开头:是发给 adb server 本身的控制命令,用来选择设备、管理转发;
  • server 解析完 host 指令之后,建立一条通往板子 adbd 的数据通道,之后才开始走标准 ADB 二进制协议包(A_OPEN/A_OKAY/A_WRTE/A_CLSE)。

4、非常重要的分层

① 5037 端口:

PC 本地控制面,只负责管理设备、选设备、建立通道;

② 板子和 server 之间:

数据面,跑标准 ADB 多路复用协议。

5、执行 adb shell流程

① client → 127.0.0.1:5037,发 host:devices,拿到设备序列号

② client 发 host:transport:serial,告诉 server:我要切换到这台设备;

③ server 和 adbd 之间建立好数据流通道;

④ 通道建立完成,开始传输 ADB 协议包,发起 shell 服务。

二、传输层抽象

Transport,统一 USB 和 TCP

一个核心抽象:struct transport

上层协议代码(protocol、service)完全不关心底层是 USB 还是 TCP,只调用 transport 提供的 read /write 接口

1、USB transport(FunctionFS / F_ADB)

内核侧依赖:CONFIG_USB_CONFIGFS + CONFIG_USB_CONFIGFS_F_ADB(Linux5.4 内核配置项)

当板子作为 USB gadget 设备,内核会在 /dev/usb-ffs/adb/ 下面生成几个端点文件:

本质:USB 批量端点,是一种面向包的可靠传输通道,不是流式 socket,但 adbd 把它封装成和 socket 一样的读写接口。

  • ep0:控制端点
  • ep1:OUT(PC → 板子,写)
  • ep2:IN(板子 → PC,读)
  • adbd 直接 open 这两个批量端点,用 read/write 收发二进制数据包。

2、TCP transport(adb tcpip 5555)

adbd 在板子上监听 0.0.0.0:5555 的 TCP socket;

PC 的 adb server 主动连这个端口;底层就是普通字节流 TCP。

3、这样统一的好处

不管插 USB,还是连 wifi 5555,上层 ADB 协议包格式完全一模一样,这就是为什么一条命令 adb shell 两种方式都能用。

源码对应:transport.c 里面封装这两套读写实现。

三、ADB 核心协议

数据包结构 + 4 种基础包

ADB 协议是多路复用流协议:一条底层传输链路(USB 或者一条 TCP 连接),可以虚拟出很多独立的「通道(stream)」。

类比:一条网线(底层 transport),同时开多个网页、微信、文件下载;adb 的 channel 就是这个虚拟流。

1、数据包头部(每个 adb 包都带这个头)

复制代码
struct adb_msg {
    uint32_t command;    // 包类型:A_OPEN, A_OKAY, A_WRTE, A_CLSE
    uint32_t arg0;       // local id:本地通道号
    uint32_t arg1;       // remote id:对端通道号
    uint32_t data_length;// 后面payload的长度
    uint32_t data_check; // 校验
    uint32_t magic;
}
  • local id:发包方自己给这个通道分配的编号
  • remote id:对方给这个通道分配的编号

通道是双向配对的:local_id ↔ remote_id,一一绑定。

2. 四个基础命令包

就这 4 个,所有功能都靠它们组合

① A_OPEN:

打开一个新通道,请求启动一个服务 payload:服务名字串,比如 shell:、sync:、tcp:8888

例子:PC 侧发 A_OPEN,payload="shell:" → 请求 adbd 拉起 shell 服务

② A_OKAY:

确认应答包 收到 A_OPEN 之后,adbd 同意创建通道,回复 A_OKAY;

通道正式就绪,可以收发数据。

③ A_WRTE:

写数据包,承载业务 payload shell 输入字符、命令输出、push 的文件数据,全部封装在 A_WRTE 里面传输。

④ A_CLSE:

关闭通道 一端发 A_CLSE,代表这个虚拟流结束;

adbd 这边就会关闭对应的子进程、管道。

重点:一条物理连接,可以同时存在几十组不同 id 的通道,互不干扰。

比如:通道 1 跑 adb shell,通道 2 跑 adb push,通道 3 跑 forward 端口转发,这就是多路复用。

3. 一次完整通道建立流程(shell 通道示例)

① PC(adb server)

发送:A_OPEN, arg0=1, arg1=0, payload="shell:"

含义:我申请新建通道,我这边编号是 1,请你打开 shell 服务。

② 板子 adbd

收到 A_OPEN,解析 service 名字 shell:

adbd 内部:fork () 创建子进程,dup2 管道绑定 /bin/sh 的 stdin/stdout/stderr

③ adbd 回复

A_OKAY, arg0=5, arg1=1

含义:同意,我这边给这个通道分配编号 5,你的编号是 1;

通道(1<->5)建立成功。

④ 双向互发 A_WRTE

PC 输入字符 → A_WRTE → adbd → 写入 sh 的 stdin

sh 输出结果 → adbd 打包 A_WRTE → 传回 PC 展示

⑤ 退出 shell(exit 或者 ctrl+c)

任意一端发送 A_CLSE,通道销毁,回收子进程。

这就是 adb shell 的内核流转逻辑,没有魔法,就是包 + 通道 + fork + 管道转发 IO。

四、两个核心服务:shell 服务、sync 文件服务

1、shell: 服务

就是流程,adbd fork exec /bin/sh;

老版本 android-tools-4.2.2 大坑:原生不带 PTY 伪终端

  • 不带 PTY:只是普通管道;能收发字符,但是没有终端控制; 表现:没有回显、Tab 补全失效、Ctrl+C 无法中断进程
  • 带 PTY:open /dev/pts/xx,把子进程绑定到 pty,才有完整终端交互。

2、sync: 服务(adb push /adb pull /adb sync)

payload 不再是终端字符,而是一套简单的 sync 子协议: SEND、RECV、DATA、DONE;

用来分片传输文件、文件属性、长度。 文件被切成多个 A_WRTE 包分片传输,zlib 用来做压缩(对应依赖 zlib 库)。

另外还有 tcp: 服务,就是 forward/reverse 端口转发:adbd 在板子上建立本地 socket,把通道的数据转发到这个 socket。

五、USB ADB 和 TCP ADB 的差异细节

项目 USB FFS ADB TCPIP adb(5555)
底层介质 USB 批量端点,面向包 TCP 字节流,流式
内核依赖 CONFIG_USB_CONFIGFS_F_ADB 只需要网卡,不需要 gadget
adbd 启动方式 adbd 打开 ep1/ep2 端点 adbd 监听 socket 5555
优点 稳定、不需要 IP、不容易粘包 免数据线,远程调试
缺点 必须 USB 线;需要 gadget 配置 网络抖动、容易断、内网开放有安全风险

协议层:上层 A_OPEN/A_OKAY/A_WRTE/A_CLSE 完全一样,transport 层抹平差异。

相关推荐
武子康19 分钟前
单卡 A6000 跑 Qwen-Drive:怎样留下可比较的第一条基线?
linux·人工智能·深度学习
女神下凡26 分钟前
芯参谋(107):杰理AC_中科蓝讯_开发指南
linux·服务器·网络·单片机·嵌入式硬件
落羽的落羽32 分钟前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
爱和冰阔落5 小时前
【Linux网络】TCP 半包粘包怎么解决?从长度报头、JSON 拆包到网络计算器完整实战
linux·运维·网络·tcp/ip
say_fall7 小时前
【Linux网络编程】UDP套接字编程:系统编程组件、基础回显服务、InetAddr与地址转换、翻译服务与线程池聊天室
linux·服务器·网络·udp·vr
ö Constancy7 小时前
一台电脑的硬件组成与作用:按功能分类详解(Windows 与 Linux 视角)
linux·windows·电脑
江湖有缘7 小时前
基于Ubuntu部署SoduWork:企业级 AI 原生协同平台实战全流程
linux·人工智能·ubuntu·ai·soduwork
无奈笑天下16 小时前
银河麒麟上nproc命令教程详解
linux·运维·服务器
Rabitebla20 小时前
【Linux】进程控制(十二) 自定义 Shell(二):内建命令与进程工作目录管理
linux·c++·笔记·学习·bash