深入理解android卷1 第8章:深入理解Vold和Rild
·
深入理解android卷1 第8章:深入理解Vold和Rild
核心主题:存储管理守护进程(Vold)和电话守护进程(Rild)
关键知识点速查 - Vold篇
1. Vold概述
全称:Volume Daemon(卷管理守护进程)
核心职责:
- 监听内核设备插拔事件(uevent)
- 管理存储设备(SD卡、USB、OTG)
- 挂载/卸载文件系统
- 加密存储管理
架构位置:
应用层(StorageManager)
↓ Binder
MountService(Java服务)
↓ Socket
Vold(Native守护进程)
↓ Netlink
Kernel(uevent)
↓
存储设备(SD卡、USB)
2. Vold启动流程
init.rc配置:
service vold /system/bin/vold \
--blkid_context=u:r:blkid:s0 \
--blkid_untrusted_context=u:r:blkid_untrusted:s0 \
--fsck_context=u:r:fsck:s0 \
--fsck_untrusted_context=u:r:fsck_untrusted:s0
class core
ioprio be 2
socket vold stream 0660 root mount
socket cryptd stream 0660 root mount
main函数流程:
// system/vold/main.cpp
int main(int argc, char** argv) {
// 1. 创建VolumeManager单例
VolumeManager* vm = VolumeManager::Instance();
// 2. 创建NetlinkManager(监听内核事件)
NetlinkManager* nm = NetlinkManager::Instance();
// 3. 启动Netlink监听
nm->start();
// 4. 创建CommandListener(监听MountService命令)
CommandListener* cl = new CommandListener();
// 5. 启动Socket服务
if (cl->startListener()) {
exit(1);
}
// 6. 进入事件循环
while (1) {
sleep(1000);
}
}
3. Netlink事件监听
Netlink机制:
- 内核与用户空间通信的Socket机制
- 用于传递设备热插拔事件(uevent)
uevent格式:
ACTION=add
DEVPATH=/devices/platform/soc/7864900.sdhci/mmc_host/mmc0/mmc0:0001
SUBSYSTEM=block
DEVNAME=mmcblk0
DEVTYPE=disk
MAJOR=179
MINOR=0
监听流程:
void NetlinkManager::onEvent(NetlinkEvent* evt) {
const char* subsys = evt->getSubsystem();
if (!strcmp(subsys, "block")) {
// 块设备事件(SD卡、USB)
VolumeManager::Instance()->handleBlockEvent(evt);
} else if (!strcmp(subsys, "usb")) {
// USB设备事件
}
}
4. Volume管理
Volume类型:
class VolumeBase {
enum Type {
kPublic = 0, // 公共存储(SD卡)
kPrivate = 1, // 私有存储(adoptable storage)
kEmulated = 2, // 模拟存储(内部存储的分区)
kAsec = 3, // 加密容器
kObb = 4, // OBB文件(游戏数据包)
};
};
Volume状态机:
unmounted(未挂载)
↓ mount()
checking(检查文件系统)
↓ fsck
mounted(已挂载)
↓ unmount()
ejecting(弹出中)
↓
unmounted
挂载流程:
// VolumeManager::handleBlockEvent()
void VolumeManager::handleBlockEvent(NetlinkEvent* evt) {
// 1. 解析设备路径
const char* devpath = evt->findParam("DEVPATH");
// 2. 创建PublicVolume对象
auto vol = std::make_shared<PublicVolume>(device);
mDisks[device] = vol;
// 3. 创建挂载点
// /mnt/media_rw/xxxx-xxxx
// 4. 检查文件系统
// fsck -a /dev/block/vold/public:179,0
// 5. 挂载
// mount -t vfat /dev/block/vold/xxx /mnt/media_rw/xxx
// 6. 通知MountService
sendBroadcast(VolumeStateChanged);
}
5. Vold命令协议
Socket通信:
MountService Vold
│ │
├─ "volume mount xxx" ───────>│
│ │ 挂载处理
│<─ "200 volume mounted" ────┤
│ │
├─ "volume unmount xxx" ─────>│
│ │ 卸载处理
│<─ "200 volume unmounted" ──┤
命令格式:
// 客户端发送
"volume mount <volume_id>"
// 服务端响应
"200 volume <volume_id> state mounted"
// 错误响应
"400 Command failed"
6. 存储加密(FDE/FBE)
FDE(Full Disk Encryption):
- 全盘加密(Android 4.4-6.0)
- 启动时需要输入密码解密
- 解密后整个/data分区可访问
FBE(File-Based Encryption):
- 基于文件的加密(Android 7.0+)
- 用户数据分为DE(Device Encrypted)和CE(Credential Encrypted)
- DE:设备启动后即可访问(闹钟、电话)
- CE:用户解锁后才能访问(应用数据)
加密流程:
// cryptfs.c
int cryptfs_enable(int type) {
// 1. 生成加密密钥
create_crypto_blk_dev();
// 2. 格式化加密分区
format_encrypted_partition();
// 3. 挂载加密分区
mount_encrypted_partition();
// 4. 保存密钥(加密后存储)
put_crypt_ftr_and_key();
}
关键知识点速查 - Rild篇
1. Rild概述
全称:Radio Interface Layer Daemon(无线接口层守护进程)
核心职责:
- 管理Modem通信(电话、短信、数据网络)
- 与RIL库交互(厂商实现)
- 向上层提供电话服务接口
架构位置:
应用层(TelephonyManager)
↓
Phone进程(Java)
↓
RILJ(Java Binder客户端)
↓ Socket
Rild(Native守护进程)
↓
libril-xxx.so(厂商RIL库)
↓ AT命令/QMI协议
Modem(基带处理器)
2. RIL架构
三层结构:
┌────────────────────────────┐
│ Java层(RILJ) │
│ frameworks/opt/telephony │
└──────────┬─────────────────┘
↓ Socket(rild)
┌────────────────────────────┐
│ Rild(守护进程) │
│ hardware/ril/rild │
└──────────┬─────────────────┘
↓ 函数调用
┌────────────────────────────┐
│ RIL库(厂商实现) │
│ libril-xxx.so │
└──────────┬─────────────────┘
↓ AT命令
┌────────────────────────────┐
│ Modem(基带) │
└────────────────────────────┘
3. Rild启动流程
init.rc配置:
service ril-daemon /vendor/bin/hw/rild
class main
user radio
group radio cache inet misc audio log readproc wakelock
socket rild stream 660 root radio
socket rild-debug stream 660 radio system
main函数:
// hardware/ril/rild/rild.c
int main(int argc, char** argv) {
// 1. 加载RIL库
rilLibPath = "/system/lib/libril-xxx.so";
dlHandle = dlopen(rilLibPath, RTLD_NOW);
// 2. 获取RIL_Init函数
rilInit = (const RIL_RadioFunctions*)dlsym(dlHandle, "RIL_Init");
// 3. 初始化RIL库
funcs = rilInit(&s_rilEnv, argc, rilArgv);
// 4. 创建Socket监听
s_fdListen = socket_local_server("rild", ...);
// 5. 等待RILJ连接
while (1) {
s_fdCommand = accept(s_fdListen, ...);
// 6. 创建事件循环
ril_event_loop();
}
}
4. RIL请求处理
请求格式(Parcel):
┌────────────────┐
│ Request ID │ 4字节
├────────────────┤
│ Token │ 4字节(用于匹配响应)
├────────────────┤
│ Data Length │ 4字节
├────────────────┤
│ Data │ 变长
└────────────────┘
处理流程:
// 1. RILJ发送请求
RIL_REQUEST_DIAL: {
dialAddress: "10086",
clir: 0
}
// 2. Rild接收并分发
processCommandBuffer() {
request = parcel.readInt32(); // RIL_REQUEST_DIAL
token = parcel.readInt32();
// 调用RIL库函数
funcs->onRequest(request, data, datalen, token);
}
// 3. RIL库发送AT命令
ATD10086;
// 4. Modem响应
OK
// 5. RIL库回调
RIL_onRequestComplete(token, RIL_E_SUCCESS, NULL, 0);
// 6. Rild返回响应给RILJ
5. 主动上报(Unsolicited Response)
场景:
- 来电:RING
- 短信:+CMT
- 信号强度变化:+CSQ
- 网络注册状态:+CREG
处理流程:
// RIL库监听Modem主动上报
void onUnsolicited(const char* s) {
if (strStartsWith(s, "RING")) {
// 来电
RIL_onUnsolicitedResponse(
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
NULL, 0
);
} else if (strStartsWith(s, "+CMT")) {
// 短信
RIL_onUnsolicitedResponse(
RIL_UNSOL_RESPONSE_NEW_SMS,
sms, sizeof(sms)
);
}
}
// Rild转发给RILJ
sendResponse(p); // 发送到Socket
// RILJ处理
processUnsolicited(p) {
switch (response) {
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
mCallStateRegistrants.notifyRegistrants();
break;
}
}
6. AT命令示例
拨号:
AT: ATD10086;
Modem: OK
挂断:
AT: ATH
Modem: OK
发短信:
AT: AT+CMGS="13800138000"
Modem: >
AT: Hello World<Ctrl+Z>
Modem: +CMGS: 123
OK
查询信号强度:
AT: AT+CSQ
Modem: +CSQ: 25,99
OK
7. RIL命令分类
| 类别 | 命令示例 | 说明 |
|---|---|---|
| 通话 | RIL_REQUEST_DIAL | 拨号 |
| RIL_REQUEST_HANGUP | 挂断 | |
| RIL_REQUEST_ANSWER | 接听 | |
| 短信 | RIL_REQUEST_SEND_SMS | 发送短信 |
| RIL_REQUEST_SMS_ACKNOWLEDGE | 短信应答 | |
| 网络 | RIL_REQUEST_SIGNAL_STRENGTH | 信号强度 |
| RIL_REQUEST_OPERATOR | 运营商信息 | |
| SIM卡 | RIL_REQUEST_GET_IMSI | 获取IMSI |
| RIL_REQUEST_SIM_IO | SIM卡IO操作 | |
| 数据 | RIL_REQUEST_SETUP_DATA_CALL | 建立数据连接 |
| RIL_REQUEST_DEACTIVATE_DATA_CALL | 断开数据连接 |
架构图
Vold架构
┌─────────────────────────────────────┐
│ MountService(Java) │
│ frameworks/base/.../MountService │
└──────────────┬──────────────────────┘
↓ Socket(/dev/socket/vold)
┌─────────────────────────────────────┐
│ Vold(Native守护进程) │
│ ┌────────────┐ ┌────────────────┐ │
│ │CommandList-│ │ NetlinkManager │ │
│ │ ener │ │ │ │
│ │(Socket) │ │ (Netlink) │ │
│ └────────────┘ └────────┬───────┘ │
│ ↓ ↓ │
│ ┌──────────────────────────────┐ │
│ │ VolumeManager │ │
│ │ - handleBlockEvent() │ │
│ │ - mount/unmount │ │
│ └──────────────┬───────────────┘ │
└─────────────────┼───────────────────┘
↓
┌─────────────────────────────────────┐
│ Kernel(uevent) │
│ /sys/devices/.../uevent │
└─────────────────────────────────────┘
Rild架构
┌─────────────────────────────────────┐
│ RILJ(Java层) │
│ frameworks/opt/telephony/RIL.java │
└──────────────┬──────────────────────┘
↓ Socket(rild)
┌─────────────────────────────────────┐
│ Rild(守护进程) │
│ - processCommandBuffer() │
│ - sendResponse() │
└──────────────┬──────────────────────┘
↓ 函数调用
┌─────────────────────────────────────┐
│ RIL库(厂商实现) │
│ libril-xxx.so │
│ - onRequest() │
│ - onUnsolicited() │
│ - RIL_onRequestComplete() │
└──────────────┬──────────────────────┘
↓ AT命令/QMI协议
┌─────────────────────────────────────┐
│ Modem(基带处理器) │
└─────────────────────────────────────┘
重要概念
Vold部分
挂载点:
/mnt/media_rw/:Vold挂载的原始位置/storage/emulated/0/:模拟存储(内部存储)/storage/xxxx-xxxx/:外部存储(SD卡、USB)
文件系统支持:
- vfat(FAT32):兼容性最好
- exfat:支持大文件
- ext4:Linux文件系统
- f2fs:Flash友好文件系统
Rild部分
Modem类型:
- GSM/WCDMA:使用AT命令
- CDMA:使用QMI协议
- LTE:使用RRC协议
RIL库:
- reference-ril:参考实现(AT命令)
- 厂商RIL:高通、MTK、三星等
快速回忆检查点
Vold部分:
- Vold的核心职责是什么?(存储设备管理)
- Netlink用于什么?(监听内核uevent事件)
- SD卡插入后的处理流程?(uevent → Vold → mount → 通知MountService)
- FDE和FBE的区别?(全盘加密 vs 基于文件加密)
Rild部分:
- Rild的核心职责是什么?(管理Modem通信)
- RIL架构的三层是什么?(RILJ → Rild → RIL库)
- AT命令是什么?(与Modem通信的文本协议)
- Unsolicited Response的作用?(Modem主动上报事件)
与T87A0项目的关联
Vold相关:
- T87A0支持TF卡扩展存储
- 录像文件存储在SD卡
- 需要监听SD卡挂载/卸载事件
调试命令:
# 查看挂载信息
adb shell mount | grep /storage
# Vold日志
adb logcat -s Vold:V
# 手动挂载SD卡
adb shell sm list-disks
adb shell sm mount <disk_id>
# 查看存储状态
adb shell dumpsys mount
Rild相关:
- T87A0可能支持4G模块(选配)
- 用于远程告警(发短信、拨号)
注意事项:
- SD卡热插拔时停止录像
- 检查SD卡剩余空间
- 处理SD卡损坏场景(fsck失败)
关联章节:
- 无直接关联章节(Vold和Rild较独立)
实践建议:
- 分析T87A0的存储管理策略(SD卡优先级)
- 跟踪录像文件存储路径
- 模拟SD卡拔出场景测试
核心要点:
- Vold管理存储设备的热插拔和挂载
- Netlink是内核事件通知机制
- Rild是应用层与Modem通信的桥梁
- RIL库封装厂商特定的Modem协议
更多推荐

所有评论(0)