我所拥有的:我知道文件系统中安装 microSD 卡的位置,例如/storage/sdcard1
我需要:找出它对应的设备文件夹,例如/sys/class/mmc_host/mmc0
(这是到的链接/sys/devices/msm_sdcc.1/mmc_host/mmc0
)与/sys/class/mmc_host/mmc1
(这是到的链接/sys/devices/msm_sdcc.2/mmc_host/mmc1
)。
我需要找到正确的目录,以便我可以获取其下文件的内容,例如cid
、、等等。serial
oemid
我猜这/sys/class/mmc_host/mmc1
对应于安装在的 microSD 卡/storage/sdcard1
,但在某些 Android 设备上它是mmc0
。
由于我们使用的是 Android,因此与更典型的 Linux 相比,我们有一些限制:
- 不存在
/etc/mtab
或/etc/fstab
文件 - 没有
hwinfo
或hdparm
命令 dmesg
不运行(klogctl:操作不允许)df
不输出“安装在”列- 无法访问
stat()
或其他低级调用;至少在没有 NDK 开发的情况下,这是一个很深的游泳池,需要特定于体系结构的构建
df
以下是与 microSD 卡相关的输出:
Filesystem Size Used Free Blksize
/storage/sdcard1 29.0G 2.0G 27.0G 32768
(这很令人困惑,因为我认为,并mount
表明,这/storage/sdcard
是挂载点而不是文件系统)。
以及相关输出mount
:
/dev/block/vold/179:65 /mnt/media_rw/sdcard1 vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1023,gid=1023,fmask=0007,dmask=0007,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
/dev/fuse /storage/sdcard1 fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
上面显示挂载在的文件系统/storage/sdcard1
是/dev/fuse
。但是/dev/fuse
挂载在三个地方:
$ mount | grep fuse
/dev/fuse /mnt/shell/emulated fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /storage/emulated/legacy fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /storage/sdcard1 fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
并且无论如何我仍然没有找到任何方法来找出哪个/sys/class/
... 或/sys/devices/
... 目录对应/storage/sdcard1
。
因此,回答初始问题的一种方法可能是回答子问题,如何找出 /sys/class 或 /sys/devices 条目对于 FUSE 挂载的文件系统? 这至少应该可以回答这个案例的问题(但我不知道所有 Android 设备是否都以相同的方式安装 microSD 卡)。
任何建议都值得赞赏。
答案1
正如 Dan 所解释的,此文件系统由 FUSE 提供,这意味着它是在用户空间中实现的,并且您引用的挂载行并未说明正在使用哪个用户空间文件系统。因此,据我们所知,它可以是任何程序,并且可以执行任何随机操作。例如,它可能通过组合来自各种设备和/或网络的块来提供数据块,以及/或者程序员可能想到的任何其他方式。
当然,在实践中,根据上下文知识,您可能可以预期数据来自其中一个 mmc 设备。但即使这样也很难弄清楚,因为它可以通过设备映射器从该 mmc 设备获取数据(这里的情况似乎如此,我很想猜测 /storage/sdcard1 是通过 FUSE 从 /mnt/media_rw/sdcard1 提供的,而 /mnt/media_rw/sdcard1 本身来自 /dev/block/vold/179:65,而设备映射器中将其定义为来自其中一个 mmc 设备(当然,它也可能是设备的组合,因为设备映射器可以执行 RAID-0/1)。
因此,从理论上讲,您可以尝试找出(不确定如何)哪个进程与该挂载点关联(作为 FUSE 守护进程),然后查看 /proc/ 中的这个进程以查看它打开了哪些文件并从这些打开的文件中猜测它将数据带到哪里(即找出它来自 /mnt/media_rw/sdcard1),然后再次查看 /proc/mounts 以发现它来自 /dev/block/vold/179:65,然后以某种方式找出这个逻辑卷的配置(我无法在 /sys 或 /proc 中找到信息,但它可能在某个地方)以最终找到您要查找的设备。
我非常肯定,从理论上讲,你无法编写一个程序来保证它能找到你的答案。实际上,只要有足够的动力、时间和丑陋的黑客,你也许可以拼凑出适合你的用例的东西。
根据您有权访问的资源的详细信息,更简单的解决方案可能是更“全面”地进行:不要关注数据从设备到挂载点(以及返回)所采用的路径,而是查看该挂载点中的数据,然后查看各种设备上的数据,并根据它们的关联方式确定它是哪个设备。
例如,在文件系统中写入一个包含 512 字节随机数据的文件,然后在候选设备的块中查找该 512 字节的精确序列。如果您能在那里找到它,您可以打赌这就是您的答案。或者,如果您不想写入:获取文件系统上某个文件的前 512 个字节,然后在设备的块中查找它。如果仅在其中一个设备上找到它,那么您就有了答案。
答案2
目录/sys
(又名Linux 内核 sysfs)仅适用于内核对象。
您提到的设备/storage/sdcard1
是不是直接作为内核驱动程序安装,它安装在用户空间,使用保险丝。
FUSE 挂载点到特定设备的映射/sys
(如果有的话,FUSE 挂载的文件系统甚至可能没有底层内核设备)通常无法根据常规挂载信息确定,除非通过推理,例如如果它是唯一被挂载的设备(该特定类型)。
它可能可以从 FUSE 获取映射信息,但我不知道是否可以/如何获取。
答案3
有些划痕太长,无法发表评论:
将同一设备安装在多个位置(可能具有不同的读/写权限...)并不罕见。
mount | grep fuse | grep -v emulated
您示例中的 A 应该有助于在模拟安装点中进行选择。在 android 4.2.2 及更早版本中,它实际上存在
vold.fstab
,一个帮助脚本可以代替/etc/fstab
(之前是vold.conf
[1])。也许您可以解析该脚本并获得一个良好的起点。Android 4.2.2 及更早版本的语法是 [2]:dev_mount <label> <mount_point> <partition> <sysfs_path> [flags]
label
:卷的标签。mount_point
:应挂载卷的文件系统路径。partition
:分区号(从 1 开始),或第一个可用分区的“自动”。sysfs_path
:可以提供此挂载点的设备的一个或多个 sysfs 路径。 以空格分隔,并且每个都必须以 开头/
。flags
:可选的逗号分隔的标志列表,不得包含/
。可能的值包括nonremovable
和encryptable
。
对于 Android 4.3 及更高版本
init、vold 和 recovery 使用的各种 fstab 文件统一在
/fstab.<device> file
。所以你应该有你的设备名称突出显示在文件名中。
另据报道[2] 对于由 管理的外部存储卷
vold
,您应该找到以下格式:<src> <mnt_point> <type> <mnt_flags> <fs_mgr_flags>
在哪里
src
:可提供挂载点的设备下的路径sysfs
(通常挂载在)。路径必须以 开头。/sys
/
mount_point
:应挂载卷的文件系统路径。type
:卷上的文件系统类型。对于外部卡,这通常是vfat
。mnt_flags
:Vold 忽略此字段,应将其设置为默认值fs_mgr_flags
:Vold 会忽略统一文件中fstab
不包含voldmanaged=
此字段中的标志的任何行。此标志后面必须跟有描述卡的标签以及分区号或单词 auto。以下是示例:。voldmanaged=sdcard:auto
其他可能的标志包括nonremovable
、、和。encryptable=sdcard
noemulatedsd
encryptable=userdata
参考
- 问题关于 vold.conf 和 vold.fstab。
- Android 代码设备配置页。