快速简洁答案:
1. 计算分区大小
rk3288:/ # cat /proc/partitions | grep mmcblk1p14 // 筛选自己的userdata分区
179 14 4534272 mmcblk1p14
分区大小 = 4534272 * 1024Byte = 4534272KB
换算为block = 4534272KB / 512Byte = 9068544 (0x8A6000)个block
2. 用AndroidTools导出分区,分区大小为第一步计算的0x8A6000个block .
3. mount挂载到另外一台设备上读写。
具体原理、或上一步结果不正确时,见下文步骤,对照后再计算。
背景:有台设备sdcard上日志爆满,导致系统启动不起来(sdcard目录也无法挂载),需要查看原因,并删除一些日志。
由于sdcard目录挂载在userdata分区上,所以需要操作userdata分区,并修改。
受限于android上没有fdisk工具,所以查看分区大小及开始位置比较麻烦。
具体步骤如下:
1. 查看分区挂载点, 每个系统基本不一样,所以这里用通用方法
rk3288:/ # cat /proc/mounts
rootfs / rootfs ro,size=492976k,nr_inodes=121795 0 0
tmpfs /dev tmpfs rw,nosuid,relatime,size=502416k,mode=755 0 0
devpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0
proc /proc proc rw,relatime,gid=3009,hidepid=2 0 0
sysfs /sys sysfs rw,relatime 0 0
/sys/kernel/debug /sys/kernel/debug debugfs rw,relatime,mode=755 0 0
/sys/kernel/debug/tracing /sys/kernel/debug/tracing tracefs rw,relatime,mode=755 0 0
none /acct cgroup rw,relatime,cpuacct 0 0
tmpfs /mnt tmpfs rw,relatime,size=502416k,mode=755,gid=1000 0 0
none /config configfs rw,relatime 0 0
none /dev/memcg cgroup rw,relatime,memory 0 0
none /dev/cpuctl cgroup rw,relatime,cpu 0 0
none /dev/cpuset cgroup rw,relatime,cpuset,noprefix,release_agent=/sbin/cpuset_release_agent 0 0
pstore /sys/fs/pstore pstore rw,relatime 0 0
/dev/block/platform/ff0f0000.dwmmc/by-name/system /system ext4 ro,noatime,nodiratime,noauto_da_alloc,data=ordered 0 0
/dev/block/platform/ff0f0000.dwmmc/by-name/vendor1 /vendor ext4 ro,nosuid,nodev,noatime,nodiratime,discard,noauto_da_alloc,data=ordered 0 0
/dev/block/platform/ff0f0000.dwmmc/by-name/cache /cache ext4 rw,nosuid,nodev,noatime,nodiratime,discard,noauto_da_alloc,data=ordered 0 0
/dev/block/platform/ff0f0000.dwmmc/by-name/metadata /metadata ext4 rw,nosuid,nodev,noatime,nodiratime,discard,noauto_da_alloc,data=ordered 0 0
/dev/block/platform/ff0f0000.dwmmc/by-name/userdata /data f2fs rw,lazytim
e,nosuid,nodev,noatime,nodiratime,background_gc=on,discard,no_heap,user_x
attr,inline_xattr,inline_data,inline_dentry,flush_merge,extent_cache,mode=adaptive,active_logs=6,alloc_mode=reuse,fsync_mode=posix 0 0
tmpfs /storage tmpfs rw,relatime,size=502416k,mode=755,gid=1000 0 0
adb /dev/usb-ffs/adb functionfs rw,relatime 0 0
/data/media /mnt/runtime/default/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser 0 0
/data/media /storage/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser 0 0
/data/media /mnt/runtime/read/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=23 0 0
/data/media /mnt/runtime/write/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=7 0 0
1.1 按照名称来精简下上面的结果。其实上一步已经可以查看到了,在/dev/block/platform/ff0f0000.dwmmc/by-name/ 这个目录下存在对应关系。
因为有的系统是 /dev/block/mtd, 有的是其他别名,所以需要上面第一步找到路径名。然后查看:
rk3288:/ # ls -l /dev/block/platform/ff0f0000.dwmmc/by-name/
total 0
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 backup -> /dev/block/mmcblk1p8
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 boot -> /dev/block/mmcblk1p6
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 cache -> /dev/block/mmcblk1p9
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 kernel -> /dev/block/mmcblk1p5
lrwxrwxrwx 1 root root 21 2023-04-20 10:44 metadata -> /dev/block/mmcblk1p11
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 misc -> /dev/block/mmcblk1p3
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 recovery -> /dev/block/mmcblk1p7
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 resource -> /dev/block/mmcblk1p4
lrwxrwxrwx 1 root root 21 2023-04-20 10:44 system -> /dev/block/mmcblk1p10
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 trust -> /dev/block/mmcblk1p2
lrwxrwxrwx 1 root root 20 2023-04-20 10:44 uboot -> /dev/block/mmcblk1p1
lrwxrwxrwx 1 root root 21 2023-04-20 10:44 userdata -> /dev/block/mmcblk1p14
lrwxrwxrwx 1 root root 21 2023-04-20 10:44 vendor0 -> /dev/block/mmcblk1p12
lrwxrwxrwx 1 root root 21 2023-04-20 10:44 vendor1 -> /dev/block/mmcblk1p13
2. 根据上面步骤可以获取到/userdata 挂载点对应的具体分区为 /dev/blck/mmcblk1p14
然后读取分区表, 找到mmcblk1p14的大小(以block计数)。
rk3288:/ # cat /proc/partitions
major minor #blocks name
1 0 8192 ram0
1 1 8192 ram1
1 2 8192 ram2
1 3 8192 ram3
1 4 8192 ram4
1 5 8192 ram5
1 6 8192 ram6
1 7 8192 ram7
1 8 8192 ram8
1 9 8192 ram9
1 10 8192 ram10
1 11 8192 ram11
1 12 8192 ram12
1 13 8192 ram13
1 14 8192 ram14
1 15 8192 ram15
254 0 520912 zram0
179 0 7634944 mmcblk1
179 1 4096 mmcblk1p1
179 2 4096 mmcblk1p2
179 3 4096 mmcblk1p3
179 4 16384 mmcblk1p4
179 5 24576 mmcblk1p5
179 6 32768 mmcblk1p6
179 7 32768 mmcblk1p7
179 8 114688 mmcblk1p8
179 9 1048576 mmcblk1p9
179 10 1179648 mmcblk1p10
179 11 16384 mmcblk1p11
179 12 307200 mmcblk1p12
179 13 307200 mmcblk1p13
179 14 4534272 mmcblk1p14
179 96 512 mmcblk1rpmb
179 64 4096 mmcblk1boot1
179 32 4096 mmcblk1boot0
注意partitions分区每个block有1024Byte,所以userdata分区大小为: 4534272 * 1024Byte = 4534272KB
3. 另外还可以从/sys/class/block/*/*/size处查看分区大小。
rk3288:/ # cat /sys/class/block/mmcblk1p14/size
9068544
rk3288:/ # cat /proc/partitions | grep mmcblk1p14
179 14 4534272 mmcblk1p14
userdata分区有9068544个block,所以userdata分区大小为
size = 9068544 * 512Byte = 4534272 * 1024Byte = 4534272KB
两个位置显示的块大小不相同,原因:
/sys/dev/block/*/*/size
shows the size in 512-byte sectors.
/proc/partitions
shows the size in 1024-byte blocks.
查询Flash上block大小是512Byte, 所以userdata有 4534272KB / 512Byte = 9068544 (0x8A6000)个block
PS. 有些系统Flash的block并不是512Byte,可能为1024Byte或其他值。
3.1 查看分区开始位置
cat /sys/class/block/mmcblk1p14/start
6201344
查询userdata分区开始位置在6201344(0x005EA000) * 512Byte 字节处。
但是使用的rk3399系列有0x2000的偏移,减去偏移量后,开始位置在:0x005EA000 - 0x00002000 = 0x005E8000 ( * 512Byte ) 字节处。
查看Flash信息得知flash的block也是512Byte, 所以 开始位置为 0x005E8000 ( * 512Byte ) / 512Byte = 0x005E8000
另外还可以直接通过AndroidTools直接读取分区表,但读取到的userdata分区大小是错误的,如下:
结合上面得到的分区大小,及开始位置,就可以导出分区镜像了。可以用厂家工具,或者dd命令,任何自己熟练的工具,都可以。
4. 挂载分区并编辑
Android下userdata分区通常为f2fs文件系统,把上面的分区导出img后,很多软件暂时不支持(打开后空白),可以通过下面的方式挂载到linux文件系统上,进行修改编辑。
mount -t f2fs -o loop /your/android_userdata.img /mnt
镜像挂载完成后,与常规操作方式一致,不再详述。