AndroidSD卡挂载流程浅析.docx

上传人:b****5 文档编号:30284660 上传时间:2023-08-13 格式:DOCX 页数:102 大小:55.12KB
下载 相关 举报
AndroidSD卡挂载流程浅析.docx_第1页
第1页 / 共102页
AndroidSD卡挂载流程浅析.docx_第2页
第2页 / 共102页
AndroidSD卡挂载流程浅析.docx_第3页
第3页 / 共102页
AndroidSD卡挂载流程浅析.docx_第4页
第4页 / 共102页
AndroidSD卡挂载流程浅析.docx_第5页
第5页 / 共102页
点击查看更多>>
下载资源
资源描述

AndroidSD卡挂载流程浅析.docx

《AndroidSD卡挂载流程浅析.docx》由会员分享,可在线阅读,更多相关《AndroidSD卡挂载流程浅析.docx(102页珍藏版)》请在冰豆网上搜索。

AndroidSD卡挂载流程浅析.docx

AndroidSD卡挂载流程浅析

Android2.3中关于SD卡挂载简介

     在Android2.3中,当SD卡插入系统之后,系统会自动挂载。

Vold就是负责挂载SD卡的,vold的全称是volumedaemon。

实际上是负责完成系统的CDROM,USB大容量存储,MMC卡(后文有简介,具体请XX)等扩展存储的挂载任务自动完成的守护进程。

它提供的主要特点是支持这些存储外设的热插拔。

在Android上的这个vold系统和GNU/Linux的之间存在很大的差异。

自Android2.2开始,vold又做了大改动,升级为vold2.0,之前的配置文件是system/etc/vold.conf,vold2.0变为system/etc/vold.fstab。

vold.fstab中的内容显示如下:

dev_mountsdcard/mnt/sdcardauto/devices/platform/goldfish_mmc.0/devices/platform/msm_sdcc.2/mmc_host/mmc1

##Exampleofadualcardsetup

#dev_mountleft_sdcard /sdcard1 auto/devices/platform/goldfish_mmc.0/devices/platform/msm_sdcc.2/mmc_host/mmc1

#dev_mountright_sdcard/sdcard2 auto/devices/platform/goldfish_mmc.1/devices/platform/msm_sdcc.3/mmc_host/mmc1

##Exampleofspecifyingaspecificpartitionformounts

#dev_mountsdcard/sdcard2/devices/platform/goldfish_mmc.0/devices/platform/msm_sdcc.2/mmc_host/mmc1

可以看到大部分是注释,最重要的为以下这句:

dev_mountsdcard/mnt/sdcardauto/devices/platform/goldfish_mmc.0/devices/platform/msm_sdcc.2/mmc_host/mmc1

这句代码意思是:

外置SD卡的挂载路径,auto代表挂载SD卡的第一个分区,后面是vold监测的路径,当插入sd时,/devices/platform/msm_sdcc.2/mmc_host/mmc1路径下会多出一个文件夹,在该文件夹中包含了SD卡的各种ID信息,以及生产日期等。

如果把sd卡插入设备,在/dev/block/目录下面也会多出几个设备节点,证明sd卡的驱动已经成功加载。

我自己测试的目录下面会形成mmcblk0 和mmcblk0p1节点,注意:

这两个节点的意思,mmcblk0代表第一个SD卡设备,mmcblk0p1代表第一个SD卡设备的第一个分区。

真正挂载到系统中的是mmcblk0p1而不是mmcblk0,这一点很重要。

PS:

MMC(MultiMediaCard)卡由西门子公司和首推CF的SanDisk于1997年推出。

1998年1月十四家公司联合成立了MMC协会(MultiMediaCardAssociation简称MMCA),现在已经有超过84个成员。

MMC的发展目标主要是针对数码影像、音乐、手机、PDA、电子书、玩具等产品,号称是目前世界上最小的FlashMemory存贮卡,尺寸只有32mmx24mmx1.4mm。

虽然比SmartMedia厚,但整体体积却比SmartMedia小,而且也比SmartMedia轻,只有1.5克。

MMC也是把存贮单元和控制器一同做到了卡上,智能的控制器使得MMC保证兼容性和灵活性。

MMC_XX百科

SD/MMC卡的设备构造差不多,不过MMC当时的设计比SD小一半。

所以,SD/MMC的驱动通用,进一步的,Linux的设备节点就延续了MMC的这个名字,后面的blk是块设备这个英文的简写,mmcblk也就是“mmc/sd块设备”,0就是这个mmc/sd设备的顺序编号,p1就是第一个分区。

挂载流程简析

内核层(kernel):

当有新的SD/USB设备插入时,kernel将自动检测并加载对应的驱动,同时kernel中的sysfs机制会在有新的驱动加载时给用户层发送相应的event,然后将kernel产生的这些event传递给vold。

用户层(user):

用户层通过sysfs可以接收来自kernel的uevent,这些收到的信息可以在/sys/block/mmcblk0下用命令cat*来查看,如:

#cat*

bdi:

invalidlength

10

179:

0

device:

invalidlength

8

holders:

invalidlength

power:

invalidlength

queue:

invalidlength

8

0

0

524288

slaves:

invalidlength

    278     813    8686    1050       0       0       0       0       0     240    1040

subsystem:

invalidlength

MAJOR=179

MINOR=0

DEVTYPE=disk

NPARTS=0

#

如果这时候在终端输入"pwd"指令,大家会发现路径并不是我们之前进入的路径/sys/block/mmcblk0,而是/sys/devices/platform/goldfish_mmc.0/mmc_host/mmc0/mmc0:

e118/block/mmcblk0。

其中mmc0:

e118这个文件是插入SD卡之后生成的文件。

Sysfs传递来的是一个多行的文档,vold需要解析这个文档。

Vold将处理之后的事件传递给MountService,然后MoutService会将信息进一步处理传递给StorageManager,最后我们可以在系统设置界面看到SD卡挂载成功的信息,这包括了SD卡的总容量以及可用空间如下图:

SD卡的挂载流程大致如此,MountServie实际上还会通知PackageManagerService,因为这里分析的是SD卡挂载从底层到上层的表现,因此这里暂不分析。

简约流程图如下:

 在上一篇博文《Android2.3SD卡挂载流程浅析

(一)》主要简单的介绍了SD卡的挂载流程。

包括了从内核层到用户层事件消息的传递,以及Vold的简介。

本文将继续介绍SD卡的挂载,但文中并不会涉及代码的详细分析,因为这部分网上已有资料,我会在文章结尾贴出来供大家参考。

本文主要目的是一方面对自己学习这一部分的总结,另一方面希望大家能够指出文中理解错误的地方。

     1.SD卡挂载流程图

     SD卡的挂载流程图如下:

       绿色箭头:

表示插入SD卡后事件传递以及SD卡挂载

       红色箭头:

表示挂载成功后的消息传递流程

       黄色箭头:

表示MountService发出挂载/卸载SD卡的命令

       大家可能对图中突然出现的这么多的名称感到奇怪,这些都是在Android2.3源码中可以找到的,接下来我会为大家一一解释这些类的作用。

      2.各个文件的主要作用

    

(1)Kernel:

这个是系统内核啦。

不是我要分析的文件,本文涉及内容不是内核级的哦!

(努力学习中...)

      

(2)NetlinkManager:

全称是NetlinkManager.cpp位于Android2.3源码位置/system/vold/NetlinkManager.cpp。

该类的主要通过引用NetlinkHandler类中的onEvent()方法来接收来自内核的事件消息,NetlinkHandler位于/system/vold/NetlinkHandler.cpp。

    (3)VolumeManager:

全称是VolumeManager.cpp位于Android2.3源码位置/system/vold/VolumeManager.cpp。

该类的主要作用是接收经过NetlinkManager处理过后的事件消息。

因为我们这里是SD卡的挂载,因此经过NetlinkManager处理过后的消息会分为五种,分别是:

block,switch,usb_composite,battery,power_supply。

这里SD卡挂载的事件是block。

      (4)DirectVolume:

位于/system/vold/DirectVolume.cpp。

该类的是一个工具类,主要负责对传入的事件进行进一步的处理,block事件又可以分为:

Add,Removed,Change,Noaction这四种。

后文通过介绍Add事件展开。

      (5)Volume:

Volume.cpp位于/system/vold/Volume.cpp,该类是负责SD卡挂载的主要类。

Volume.cpp主要负责检查SD卡格式,以及对复合要求的SD卡进行挂载,并通过Socket将消息SD卡挂载的消息传递给NativeDaemonConnector。

      (8)StorageManaer:

位于frameworks/base/core/java/andriod/os/storage/StorageManager.java。

在该类的说明中有提到,该类是系统存储服务的接口。

在系统设置中,有Storage相关项,同时Setting也注册了该类的监听器。

而StorageManager又将自己的监听器注册到了MountService中,因此该类主要用于上层应用获取SD卡状态。

    通过上文对各个文件的作用简介,以及整个SD卡的挂载流程图可以知道,Android系统是如何从底层获取SD卡挂载信息的。

      后文将继续分析程序调用流程图。

在前面两篇博文《Android2.3SD卡挂载流程浅析

(一)》《Android2.3SD卡挂载流程浅析

(二)》中,主要简单介绍了SD卡的挂载流程以及所涉及的关键文件。

在《Android2.3SD卡挂载流程浅析(三)》中,将简要介绍Android2.3中Vold的运行机制,并从接收内核uevent开始介绍程序调用流程。

      1.Vold

     Vold的全称是volumedaemon。

主要负责系统对大容量存储设备(USB/SD)的挂载/卸载任务,它是一个守护进程,该进程支持这些存储外设的热插拔。

自Android2.2开始,Vold升级为vold2.0,之前的配置文件路径在system/etc/vold.conf,Android2.3之后变为system/etc/vold.fstab。

     2.Vold工作流程

    Vold的工作流程大致可以分为三个部分:

创建监听、引导、事件处理。

     

(1)创建监听

     创建监听指的是创建监听链接,一方面用于监听来自内核的uevent,另一方面用于监听来自上层的控制命令,这些命令包括控制SD卡的挂载与卸载,这里所说的链接也就是Socket。

在Android系统启动的时候,init进程会去解析init.rc文件,在该文件中,有如下代码:

Servicevold/system/bin/vold

            Socketvoldstream0660rootmount

            Ipriobe2

     这样系统会在启动的时候创建与上层通信的Socket。

     在Android2.3源码/system/vold路径下的main.cpp中创建了与内核通信的Socket。

在main.cpp中通过实例化VolumeManager和NetlinkManager时创建。

     

(2)引导

     Vold进程启动时候会对现有的外部存储设备进行检查。

首先加载并解析vold.fstab,并检查挂载点是否已被挂载。

然后执行SD卡的挂载,最后处理USB大容量存储。

因为系统是按行解析的,通过查看vold.fstab可以很清楚的知道这一点。

vold.fatab中最重要的语句:

dev_mount       sdcard        /mnt/sdcard             auto                   /devices/platform/goldfish_mmc.0             /devices/platform/msm_sdcc.2/mmc_host/mmc1

dev_mount                                      

挂载命令           标签               挂载点             子分区个数               挂载路径

注:

      子分区个数如果为auto则表示只有1个子分区,也可以为任何不为0的整数。

      参数之间不能有空格,只能以tab为间隔(注意:

这里为了对齐因此采用空格隔开,如果自行修改vold.fstab之后加以空格的话系统会识别不到的)。

      如果vold.fstab解析无误,VolueManager将创建DirectVolume,若vold.fstab解析不存在或者打开失败,Vold将会读取Linux内核中的参数,此时如果参数中存在SDCARD(也就是SD的默认路径),VolumeManager则会创建AutoVolume,如果不存在这个默认路径那么就不会创建。

     (3)事件处理

     通过对两个socket的监听,完成对事件的处理以及对上层应用的响应。

      a.    Kernel发出uevent

      NetlinkManager检测到kernel发出的uevent,解析后调用NetlinkHandler:

:

onEvent()方法。

该方法会分别处理不同的事件,这里重要的事件有:

      “block”事件主要指Volume的mount、unmount、createAsec等。

由VolumeManager的handleBlockEvent(evt)来处理,根据多态性最终将会调用AutoVolume或者DirectVolume的handleBlockEvent方法来处理。

      “switch”事件主要指Volume的connet、disconnet等。

根据相关操作,改变设备参数(设备类型、挂载点等)通过CommandListener告知FrameWork层。

      b.   FrameWork发出控制命令

      与a相反,CommandListener检测到FrameWork层的命令(MountService发出的命令)调用VolumeManager的函数,VolumeManager找出对应的Volume,调用Volume函数去挂载/卸载操作。

而Volume类中的相关操作最终通过调用Linux函数完成。

    这里再次贴上这张流程图:

            3.SD卡挂载流程代码浅析

     这里只是简要的分析SD卡挂载过程中重要的代码调用,并没有深入分析代码,因为这一部分网上已有牛人比较详尽的分析了,后面我会贴出这些参考文章。

      整个过程从Kernel检测到SD卡插入事件开始,之前的一些硬件中断的触发以及driver的加载这里并不叙述,一直到SD卡挂载消息更新到“Android——系统设置——存储”一项中。

      1.   Kernel发出SD卡插入uevent。

      2.   NetlinkHandler:

:

onEvent()接收内核发出的uevent并进行解析。

      3.   VolumeManager:

:

handlBlockEvent()处理经过第二步处理后的事件。

      4.   接下来调用DirectVolume:

:

handleBlockEvent()。

             在该方法中主要有两点需要注意:

             第一,程序首先会遍历mPath容器,寻找与event对应的sysfs_path是否存在与mPath容器中。

             第二,针对event中的action有4种处理方式:

Add,Removed,Change,Noaction。

             例如:

在Addaction中会有如下操作(因为我们这里所讲的是SD卡的挂载流程,因此以Add来说明),首先创建设备节点,其次对disk和partition两种格式的设备分别进行处理。

SD卡属于disk类型。

      5.   经过上一步之后会调用DirectVolume:

:

handleDiskAdded()方法,在该方法中会广播diskinsert消息。

      6.   SocketListener:

:

runListener会接收DirectVolume:

:

handleDiskAdded()广播的消息。

该方法主要完成对event中数据的获取,通过Socket。

(PS:

这里的SocketListener.cpp位于Android源码/system/core/libsysutils/src/中,后文的FramworkListener.cpp也是,之前自己找了很久T_T)

      7.   调用FrameworkListener:

:

onDataAvailable()方法处理接收到的消息内容。

      8.   FrameworkListener:

:

dispatchCommand()该方法用于分发指令。

      9.    在FrameworkListener:

:

dispatchCommand()方法中,通过runCommand()方法去调用相应的指令。

     10.  在/system/vold/CommandListener.cpp中有runCommand()的具体实现。

在该类中可以找到这个方法:

CommandListener:

:

VolumeCmd:

:

runCommand(),从字面意思上来看这个方法就是对Volume分发指令的解析。

该方法中会执行“mount”函数:

vm->mountVolume(arg[2])。

    11.   mountVolume(arg[2])在VolumeManager:

:

mountVolume()中实现,在该方法中调用v->mountVol()。

    12.   mountVol()方法在Volume:

:

mountVol()中实现,该函数是真正的挂载函数。

(在该方法中,后续的处理都在该方法中,在Mount过程中会广播相应的消息给上层,通过setState()函数。

    13.   setState(Volume:

:

Checking);广播给上层,正在检查SD卡,为挂载做准备。

    14.   Fat:

:

check();SD卡检查方法,检查SD卡是否是FAT格式。

    15.   Fat:

:

doMount()挂载SD卡。

    至此,SD的挂载已算初步完成,接下来应该将SD卡挂载后的消息发送给上层,在13中也提到过,在挂载以及检查的过程中其实也有发送消息给上层的。

    16.   MountService的构造函数中会开启监听线程,用于监听来自vold的socket信息。

             Threadthread=newThread(mConnector,VOLD_TAG);thread.start();

    17.   mConnector是NativeDaemonConnector的对象,NativeDaemonConnector继承了Runnable并Override了run方法。

在run方法中通过一个while(true)调用ListenToSocket()方法来实现实时监听。

    18.   在ListenToSocket()中,首先建立与Vold通信的SocketServer端,然后调用MountService中的onDaemonConnected()方法。

(PS:

Java与Native通信可以通过JNI,那么Native与Java通信就需要通过Socket来实现了。

Android中Native与Frameworks通信

前面的三篇博文《Android2.3SD卡挂载流程浅析

(一)》、《Android2.3SD卡挂载流程浅析

(二)》、《Android2.3SD卡挂载流程浅析(三)》的分析,知道了SD卡挂载的消息是如何从底层传递到上层的,在《Android2.3SD卡挂载流程浅析(三)》中,我们已经知道了最后是在updatePublicVolumeState()中调用onStorageStateChanged(),从而达到更新SD卡挂载信息的。

在本文《Android2.3SD卡挂载流程浅析(四)》中,我会将前文提到的程序调用流程图画出来,并对代码进行简单的分析。

     首先,还是挂出这张老图(因为每次都用这张图0_0...)。

      就权当复习吧,这是SD卡的整个挂载流程,而程序的调用也是根据这个流程图来的。

      1.接收并处理uevent

      首先是接收因为插入SD卡被内核检测到而发出的Event;

      NetlinkHandler:

:

onEvent(NetlinkEvent*evt)

//代码路径:

AndroidSourcecode2.3/system/vold/NetlinkHandler.cpp

//该方法主要通过evt->getSubsystem();方法来获取系统的event

viewplain

1.void NetlinkHandler:

:

onEvent(NetlinkEvent *evt) {  

2.    VolumeManager *vm = VolumeManager:

:

Instance();  

3.    const char *subsys = evt->getSubsystem();  

4.    if (!

subsys) {  

5.        SLOGW("No subsystem found in netlink event");  

6.        return;  

7.    }  

8.    if (!

strcmp(subsys, "block")) {  

9.        vm->handleBlockEvent(evt);  

10.    } else if (!

strcmp(subsys, "switch")) {  

11.        vm->handl

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 经济学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1