Android4.4----Vold挂载管理分析USB挂载(三)
来源:互联网 发布:app下载软件 编辑:程序博客网 时间:2024/06/12 01:24
在上一篇Android4.4----Vold挂载管理分析USB挂载(二)中分析了Vold如何接收kernel的uevent并传递到VolumeManager的过程,这里继上篇文章继续分析VolumeManager接收到uevent事件后的处理过程!
那我们先分析一下VolumeManager!
一:VolumeManager
VolumeManager就是整个Android 磁盘挂载Vold机制的核心调度,上下连接的中转站!
在system/vold/main.cpp的主函数中
/* Create our singleton managers */ if (!(vm = VolumeManager::Instance())) {//构造VolumeManager SLOGE("Unable to create VolumeManager"); exit(1); };........................ vm->setBroadcaster((SocketListener *) cl);......................... if (vm->start()) {//没有做什么动作 SLOGE("Unable to start VolumeManager (%s)", strerror(errno)); exit(1); } if (process_config(vm)) { SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno)); }
VolumeManager::VolumeManager() { mDebug = false; mVolumes = new VolumeCollection();//在构造函数中new一个VolumeCollection用来保存Volume的容器 mActiveContainers = new AsecIdCollection();//活动容器,mount/unmount asec obb时的记录 mBroadcaster = NULL;//指向SocketListener,用于发送挂载事件 mUmsSharingCount = 0; mSavedDirtyRatio = -1; // set dirty ratio to 0 when UMS is active mUmsDirtyRatio = 0; mVolManagerDisabled = 0;}
加打印看了一下process_config(vm),发现是去解析fstab.madison文件,但是在真正做动作的地方没有跑进去,也就是说main函数里面最主要的就是new了一个VolumeCollection容器
然后接着看上篇接收到kernel的uevent后的动作!
vm->handleBlockEvent(evt);
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) { const char *devpath = evt->findParam("DEVPATH"); const char *devtype = evt->findParam("DEVTYPE"); const char *dn = evt->findParam("DEVNAME"); int major = -1; int minor = -1; bool isRawDisk = false; bool isPartition = false; int partIdx = -1; bool isSDCard = false; char device[255]; char uuid[255]; VolumeCollection::iterator it; bool hit = false; static bool preDiskChangeEvent = false;............. major = atoi(evt->findParam("MAJOR")); minor = atoi(evt->findParam("MINOR"));........... snprintf(device,255,"/dev/block/vold/%d:%d",major,minor); SLOGD("Javen.tang handlerBlockEvent major = %d, minor = %d, device = %s, devtype = %s\n", major, minor, device ,devtype);...........if (isRawDisk || isPartition) { //first find uuid from cache UUIDCache::Entry *entry = uuidCache.searchEntry(device); if (evt->getAction() == NetlinkEvent::NlActionAdd) { mode_t mode = 0660 | S_IFBLK; dev_t dev = (major << 8) | minor; //if device has been now added, not add again if (entry != NULL && entry->uuid != NULL) { return; } if (mknod(device, mode, dev) < 0) {//创建设备索引点 if (errno != EEXIST) { return ; } } if (!getVolumeUUID(device, uuid, 255)) {//根据device获取一个uuid #ifdef NETLINK_DEBUG SLOGD("can not get the uuid of %s when device add",device); #endif return ; }........ if (!hit) { static char index = 'a'-1; char * mountPoint = NULL; const char *dp = NULL; Volume *volume = NULL; #ifdef NETLINK_DEBUG SLOGW("No volumes handled block event for '%s'", devpath); #endif if (evt->getAction() != NetlinkEvent::NlActionAdd) { return; }..........} else { if (preDiskChangeEvent) { ++index; preDiskChangeEvent = false; } }........... else if (isPartition) { asprintf(&mountPoint,"/mnt/usb/sd%c%i",index,partIdx);//U盘的挂载点 }............ volume = new DirectVolume(this, &rec, flags); addVolume(volume);//根据挂载点new一个volume,然后add到mVolumes容器中去........... if ( volume->handleBlockEvent(evt) !=0 ) {//然后执行volume->handleBlockEvent(evt) SLOGD("New add volume fail to handle the event of %s",devpath); }注意当我们插上U盘时,会创建两个索引点,一个disk,一个partition,我们真正挂载的是partition
D/Vold ( 976): Javen.tang handlerBlockEvent major = 8, minor = 0, device = /dev/block/vold/8:0, devtype = diskD/Vold ( 976): Javen.tang handlerBlockEvent major = 8, minor = 1, device = /dev/block/vold/8:1, devtype = partition也就是说在VolumeManager中的handleBlockEvent主要做了这几件事
1、根据主次设备号创建索引点;
2、寻找挂载点,这里U盘的挂载点为/mnt/usb/sd%c%i;
3、根据挂载点创建一个DirectVolume,DirectVolume是继承于Volume,Volume就想当于一个存储设备,new了一个Volume后add到mVolumes这个容器中去;
4、调用volume的handleBlockEvent(evt)函数;
二:DirectVolume
接着看看DirectVolume的handleBlockEvent(evt)函数!
if (!strcmp(devtype, "disk")) { handleDiskAdded(dp, evt); } else { handlePartitionAdded(dp, evt); }
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); // MStar Android Patch Begin char msg[255]; // MStar Android Patch End int part_num; //devpath = /devices/platform/Mstar-ehci-1.0/usb4/4-1/4-1:1.0/host1/target1:0:0/1:0:0:0/block/sda/sda1 const char *tmp = evt->findParam("PARTN"); if (tmp) { part_num = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'PARTN'"); part_num = 1; }......................... if (getState() != Volume::State_Formatting) { setState(Volume::State_Idle); snprintf(msg, sizeof(msg), "Volume %s %s Partition Added (%d:%d)", getLabel(), getFuseMountpoint(), mDiskMajor, mDiskMinor); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted, msg, false); }
void Volume::setState(int state) { char msg[255]; int oldState = mState; if (oldState == state) { SLOGW("Duplicate state (%d)\n", state); return; } if ((oldState == Volume::State_Pending) && (state != Volume::State_Idle)) { mRetryMount = false; } mState = state; SLOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel, oldState, stateToStr(oldState), mState, stateToStr(mState)); snprintf(msg, sizeof(msg), "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(), getFuseMountpoint(), oldState, stateToStr(oldState), mState, stateToStr(mState)); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange, msg, false);}这里主要会发送两个广播到frameworks的MountService中去。
先在Volume::setState中通过mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,msg, false);发送一个VolumeStateChange类型的广播,代表挂载状态在改变,发送的信息为msg,msg的打印如下:
D/Vold ( 977): Javen.tang setState msg=Volume CAA5-CD0B /mnt/usb/sda1 state changed from 0 (No-Media) to 1 (Idle-Unmounted)然后接着调用mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,msg, false);发送一个VolumeDiskInserted类型的广播,代表U盘插入的意思,信息也是msg,打印msg信息可以看到:
D/DirectVolume( 977): Javen.tang msg=Volume CAA5-CD0B /mnt/usb/sda1 Partition Added (8:1)
接下来就要到jb4.4-kikat/frameworks/base/services/java/com/android/server/MountService.java的onEvent()方法中去查看接收到广播之后执行的动作了!
- Android4.4----Vold挂载管理分析USB挂载(三)
- Android4.4----Vold挂载管理分析USB挂载(二)
- Android4.4----Vold挂载管理分析USB挂载(四)
- Android4.4----Vold挂载管理分析(一)
- android usb挂载分析----vold启动
- android usb挂载分析----vold启动
- android usb挂载分析----vold启动
- android usb挂载分析----vold启动
- android usb挂载分析---vold处理内核消息
- android usb挂载分析---FrameWork层处理vold消息
- android usb挂载分析---vold处理内核消息
- android usb挂载分析---vold处理内核消息
- vold挂载管理
- vold挂载管理
- Android—— 4.2 Vold挂载管理_VolumeManager (三)
- Android4.0 USB挂载内核驱动层流程分析(三)
- Android4.0 USB挂载内核驱动层流程分析(三)
- android usb挂载分析---FrameWork层处理收到的vold消息
- 查看linux 是32位还是64位的命令
- 替换空格和清除空格
- 设计模式系列-----------装饰器模式(Decorator)
- MYSQL + MHA +keepalive + VIP安装配置(一)--MYSQL安装配置
- memset函数导致内存泄露的问题
- Android4.4----Vold挂载管理分析USB挂载(三)
- python 安装第三方库 PIL
- Android个人笔记 - Google Android揭秘_第二章
- 微信支付timeStamp invalid
- linux shell随记
- MYSQL + MHA +keepalive + VIP安装配置(二)--MHA的配置
- Android开源git40个App源码
- 深度解析C++模版
- 6月风怒(2)