Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2122691
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: Android平台

2014-08-01 17:02:56

1. vold的启动过程
在system/vold/main.cpp中
  1. int main() {
  2.     mkdir("/dev/block/vold", 0755);
  3.     VolumeManager *vm = VolumeManager::Instance();
  4.     NetlinkManager *nm = NetlinkManager::Instance();
  5.     CommandListener *cl = new CommandListener();
  6.     vm->setBroadcaster((SocketListener *) cl);
  7.     nm->setBroadcaster((SocketListener *) cl);

  8.     vm->start();
  9.     process_config(vm);

  10.     nm->start();

  11.     coldboot("/sys/block");
  12.     cl->startListener();
  13.     while(1) {
  14.         sleep(1000);
  15.     }
  16.     exit(0);
  17. }
在./system/vold/NetlinkManager.cpp中
  1. int NetlinkManager::start() {
  2.     //创建NET_LINK的socket
  3.     ...
  4.     //启动NetlinkHandler监听内核netlink事件
  5.     mHandler = new NetlinkHandler(mSock);
  6.     mHandler->start();  //这个start就是让NetlinkHandler->startListener            
  7.     return 0;
  8. }
2. 当有u盘插入时
NetlinkHandler->startListener会调用system/core/libsysutils/src/SocketListener.cpp中的startListener
它会用select轮询所有的socket_fd,当数据有变化时,会调用./core/libsysutils/src/NetlinkListener.cpp中的onDataAvailable函数。
这个onDataAvailable会将收到的事件解析到NetlinkEvent中,解析完成后调用NetlinkHandler的onEvent

转了一圈又回来了,在./system/vold/NetlinkHandler.cpp
  1. void NetlinkHandler::onEvent(NetlinkEvent *evt) {
  2.     VolumeManager *vm = VolumeManager::Instance();
  3.     const char *subsys = evt->getSubsystem();
  4.     if (!strcmp(subsys, "block")) {    //只对block事件反应
  5.         vm->handleBlockEvent(evt);
  6.     }
  7. }
在./system/vold/VolumeManager.cpp中
  1. void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
  2.     const char *devpath = evt->findParam("DEVPATH");
  3.     VolumeCollection::iterator it;
  4.     bool hit = false;
  5.     //这个mVolumes是在main函数的process_config在解析/etc/fstab.vold中添加的
  6.     for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
  7.         if (!(*it)->handleBlockEvent(evt)) {
  8.             hit = true;
  9.             break;
  10.         }
  11.     }
  12. }
在./system/vold/DirectVolume.cpp中
  1. int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
  2.     const char *dp = evt->findParam("DEVPATH");
  3.     PathCollection::iterator it;
  4.     for (it = mPaths->begin(); it != mPaths->end(); ++it) {
  5.         //it是从etc/vold.fstab中解析出来物理上的挂载点,
  6.         //即u盘连到了哪个usb host上
  7.         if (!strncmp(dp, *it, strlen(*it))) {
  8.             int action = evt->getAction();
  9.             const char *devtype = evt->findParam("DEVTYPE");
  10.            
  11.             //这儿只关心add时的情景
  12.             //解析主次设备号并在/dev/block/vold/ 下创建结点
  13.             ...
  14.             
  15.             if (!strcmp(devtype, "disk")) {
  16.                 handleDiskAdded(dp, evt);
  17.             } else {
  18.                 handlePartitionAdded(dp, evt);
  19.             }

  20.             if (getState() == Volume::State_Idle) {
  21.                 char msg[255];
  22.                 snprintf(msg, sizeof(msg),"Volume %s %s disk inserted (%d:%d)", getLabel(),
  23.                          getMountpoint(), mDiskMajor, mDiskMinor);
  24.                 mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,msg, false);
  25.             }
  26.             return 0;
  27.         }
  28.     }
  29.     return -1;
  30. }
一个设备插入时先disk,然后partition
  1. void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) {
  2.     //查找disk中的分区数
  3.     。。。。  findParam("NPARTS");//是整个磁盘的分区数
  4.     //并根据分区数生成mask, 1个分区mask=2
  5.     ...
  6.     mPendingPartMap = mask = 2;
  7.     //如果没有分区数,设置状态为Idle
  8.     //有分区则置为PENDIng
  9.     if (mDiskNumParts == 0) {
  10.         setState(Volume::State_Idle);
  11.     } else {
  12.         setState(Volume::State_Pending);
  13.     }
  14. }
枚举到partion时
  1. void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) {
  2.     //查找disk中的分区数  
  3.     findParam("PARTN"); //是当前分区的号码
  4.      。。。。
  5.     mPartsEventCnt = 分区数;
  6.     mPartMinors[part_num -1] = minor;
  7.     // mPendingPartMap &= ~(1 << part_num);
        mPendingPartMap &= ~(1 << mPartsEventCnt);
  8.     if (!mPendingPartMap) {
  9.         if (getState() != Volume::State_Formatting) {
  10.             setState(Volume::State_Idle);  //在mount之前先将状态设为idle
  11.             if (mRetryMount == true) {
  12.                 mRetryMount = false;
  13.                 mountVol();
  14.             }
  15.         }
  16.     } 
  17. }
注意:这个判断条件 if (!mPendingPartMap),需要mPendingPartMap=0,
mPendingPartMap 是分区数的mask,
mPartsEventCnt 也是根据分区数来计算的
所以mPendingPartMap &= ~(1 << mPartsEventCnt);可以为0
但是 part_num可以为任意值,跟分区数无关,所以mPendingPartMap &= ~(1 << part_num);这个条件不正确

3. 分区的挂载
  1. int Volume::mountVol() {
  2.     //检查当前状态是否是 State_Idle
  3.     ...
  4.     //获取挂载点,并检查挂载点是否有挂载
  5.     isMountpointMounted(getMountpoint());
  6.     //根据主次设备号 MKDEV,存在 deviceNodes中
  7.     getDeviceNodes((dev_t *) &deviceNodes, V_MAX_PARTITIONS);
  8.     //一些与crypto相关的代码
  9.     ....
  10.     ///dev/block/vold目录下生成设备结点
  11.     snprintf(nodepath, sizeof(nodepath), "/dev/block/vold/%d:%d", new_major, new_minor);
  12.     createDeviceNode(nodepath, new_major, new_minor);

  13.     updateDeviceInfo(nodepath, new_major, new_minor);


  14.     getDeviceNodes((dev_t *) &deviceNodes, V_MAX_PARTITIONS);
  15.         
  16.     for (i = 0; i < n; i++) {
  17.         char devicePath[255];
  18.         memset(devicePath, 0, 255);
  19.         sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
  20.                 MINOR(deviceNodes[i]));

  21.         setState(Volume::State_Checking);
  22.       
  23.         //检查文件系统,并挂载
  24.         ....
  25.       
  26. }

4. 挂载src的确认


5. 挂载tag的确认




阅读(886) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~