1. vold的启动过程
在system/vold/main.cpp中
-
int main() {
-
mkdir("/dev/block/vold", 0755);
-
VolumeManager *vm = VolumeManager::Instance();
-
NetlinkManager *nm = NetlinkManager::Instance();
-
CommandListener *cl = new CommandListener();
-
vm->setBroadcaster((SocketListener *) cl);
-
nm->setBroadcaster((SocketListener *) cl);
-
-
vm->start();
-
process_config(vm);
-
-
nm->start();
-
-
coldboot("/sys/block");
-
cl->startListener();
-
while(1) {
-
sleep(1000);
-
}
-
exit(0);
-
}
在./system/vold/NetlinkManager.cpp中
-
int NetlinkManager::start() {
-
//创建NET_LINK的socket
-
...
-
//启动NetlinkHandler监听内核netlink事件
-
mHandler = new NetlinkHandler(mSock);
-
mHandler->start(); //这个start就是让NetlinkHandler->startListener
-
return 0;
-
}
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
-
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
-
VolumeManager *vm = VolumeManager::Instance();
-
const char *subsys = evt->getSubsystem();
-
if (!strcmp(subsys, "block")) { //只对block事件反应
-
vm->handleBlockEvent(evt);
-
}
-
}
在./system/vold/VolumeManager.cpp中
-
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
-
const char *devpath = evt->findParam("DEVPATH");
-
VolumeCollection::iterator it;
-
bool hit = false;
-
//这个mVolumes是在main函数的process_config在解析/etc/fstab.vold中添加的
-
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
-
if (!(*it)->handleBlockEvent(evt)) {
-
hit = true;
-
break;
-
}
-
}
-
}
在./system/vold/DirectVolume.cpp中
-
int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
-
const char *dp = evt->findParam("DEVPATH");
-
PathCollection::iterator it;
-
for (it = mPaths->begin(); it != mPaths->end(); ++it) {
-
//it是从etc/vold.fstab中解析出来物理上的挂载点,
-
//即u盘连到了哪个usb host上
-
if (!strncmp(dp, *it, strlen(*it))) {
-
int action = evt->getAction();
-
const char *devtype = evt->findParam("DEVTYPE");
-
-
//这儿只关心add时的情景
-
//解析主次设备号并在/dev/block/vold/ 下创建结点
-
...
-
-
if (!strcmp(devtype, "disk")) {
-
handleDiskAdded(dp, evt);
-
} else {
-
handlePartitionAdded(dp, evt);
-
}
-
-
if (getState() == Volume::State_Idle) {
-
char msg[255];
-
snprintf(msg, sizeof(msg),"Volume %s %s disk inserted (%d:%d)", getLabel(),
-
getMountpoint(), mDiskMajor, mDiskMinor);
-
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,msg, false);
-
}
-
return 0;
-
}
-
}
-
return -1;
-
}
一个设备插入时先disk,然后partition
-
void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) {
-
//查找disk中的分区数
-
。。。。 findParam("NPARTS");//是整个磁盘的分区数
-
//并根据分区数生成mask, 1个分区mask=2
-
...
-
mPendingPartMap = mask = 2;
-
//如果没有分区数,设置状态为Idle
-
//有分区则置为PENDIng
-
if (mDiskNumParts == 0) {
-
setState(Volume::State_Idle);
-
} else {
-
setState(Volume::State_Pending);
-
}
-
}
枚举到partion时
-
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) {
-
//查找disk中的分区数
-
findParam("PARTN"); //是当前分区的号码
-
。。。。
-
mPartsEventCnt = 分区数;
-
mPartMinors[part_num -1] = minor;
-
// mPendingPartMap &= ~(1 << part_num);
mPendingPartMap &= ~(1 << mPartsEventCnt);
-
if (!mPendingPartMap) {
-
if (getState() != Volume::State_Formatting) {
-
setState(Volume::State_Idle); //在mount之前先将状态设为idle
-
if (mRetryMount == true) {
-
mRetryMount = false;
-
mountVol();
-
}
-
}
-
}
-
}
注意:这个判断条件
if (!mPendingPartMap
),需要mPendingPartMap=0,
mPendingPartMap 是分区数的mask,
mPartsEventCnt 也是根据分区数来计算的
所以mPendingPartMap &= ~(1 << mPartsEventCnt);可以为0
但是 part_num可以为任意值,跟分区数无关,所以mPendingPartMap &= ~(1 << part_num);这个条件不正确
3. 分区的挂载
-
int Volume::mountVol() {
-
//检查当前状态是否是 State_Idle
-
...
-
//获取挂载点,并检查挂载点是否有挂载
-
isMountpointMounted(getMountpoint());
-
//根据主次设备号 MKDEV,存在 deviceNodes中
-
getDeviceNodes((dev_t *) &deviceNodes, V_MAX_PARTITIONS);
-
//一些与crypto相关的代码
-
....
-
//在/dev/block/vold目录下生成设备结点
-
snprintf(nodepath, sizeof(nodepath), "/dev/block/vold/%d:%d", new_major, new_minor);
-
createDeviceNode(nodepath, new_major, new_minor);
-
-
updateDeviceInfo(nodepath, new_major, new_minor);
-
-
-
getDeviceNodes((dev_t *) &deviceNodes, V_MAX_PARTITIONS);
-
-
for (i = 0; i < n; i++) {
-
char devicePath[255];
-
memset(devicePath, 0, 255);
-
sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
-
MINOR(deviceNodes[i]));
-
-
setState(Volume::State_Checking);
-
-
//检查文件系统,并挂载
-
....
-
-
}
4. 挂载src的确认
5. 挂载tag的确认
阅读(941) | 评论(0) | 转发(0) |