这段时间为了把mmc的一个block当成sdcard内置,学习了下android的vold磁盘挂载模块,记录一下(android 4.2.2)。
一:Vold的编译及启动
vold的源码位置在android根目录 /system/vold文件下,先看这下面的android.mk:
common_src_files := VolumeManager.cpp CommandListener.cpp VoldCommand.cpp NetlinkManager.cpp NetlinkHandler.cpp Volume.cpp DirectVolume.cpp logwrapper.c Process.cpp Ext4.cpp Fat.cpp Loop.cpp Devmapper.cpp ResponseCode.cpp Xwarp.cpp cryptfs.c
…
LOCAL_MODULE:= vold
LOCAL_SRC_FILES := main.cpp $(common_src_files)
LOCAL_C_INCLUDES := $(common_c_includes)
LOCAL_CFLAGS := -Werror=format
LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
LOCAL_STATIC_LIBRARIES := libfs_mgr
include $(BUILD_EXECUTABLE)
…
最终会在out 工程目录下的system/bin 下生成一个android可执行文件vold!
关于编译还有个地方需要注意,就是vold机制将会解析的配置文件vold.fstab 这个文件的编译配置在/system/core/rootdir/Android.mk中:
ifeq ($(TARGET_PRODUCT),full)
copy_from += etc/vold.fstab
endif
ifeq ($(TARGET_PRODUCT),full_x86)
copy_from += etc/vold.fstab
endif
ifeq ($(TARGET_PRODUCT),full_mips)
copy_from += etc/vold.fstab
endif
需要需要vold.fstab,或者想添加自己的配置文件,可以在这里添加自己的TARGET_PRODUCT,编译进系统,供vold解析使用。
在/system/core/rootdir/init.rc 中作为服务进程启动,关于init.rc在android启动的作用可参考Android——启动过程详析
service vold /system/bin/vold
class core
socket vold stream 0660 root mount
ioprio be 2
关于init.rc的语法规则可参考/system/core/init/readme.txt,其中:
class
Specify a class name for the service. All services in a
named class may be started or stopped together. A service
is in the class “default” if one is not specified via the
class option.
…
socket [ [ ] ]
Create a unix domain socket named /dev/socket/ and pass
its fd to the launched process. must be “dgram”, “stream” or “seqpacket”.
User and group default to 0.
二:Vold入口
在上面通过init启动这个守护进程,入口为/system/vold/main.cpp中的main函数:
int main() {
VolumeManager *vm;
CommandListener *cl;
NetlinkManager *nm;
SLOGI(“Vold 2.1 (the revenge) firing up”);
mkdir(“/dev/block/vold”, 0755);//存放设备节点
/* Create our singleton managers */
if (!(vm = VolumeManager::Instance())) {
SLOGE(“Unable to create VolumeManager”);
exit(1);
};
if (!(nm = NetlinkManager::Instance())) {
SLOGE(“Unable to create NetlinkManager”);
exit(1);
};
cl = new CommandListener(); //构造 commandlistener 和其父类的实例,注册command
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
//设置VolumeManager NetlinkManager 这两个实例里面 一个发送广播的变量,通过隐式转换,变量类型为指向 SocketListener类的指针
if (vm->start()) {//没实际操作
SLOGE(“Unable to start VolumeManager (%s)”, strerror(errno));
exit(1);
}
//解析上面说到过的 vold.fstab 这样的配置文件,然后将解析到的内容新建抽象类(DirectVolume)的实例,然后保存到VolumeManager 中的一个容器中,后备使用
if (process_config(vm)) {
SLOGE(“Error reading configuration (%s)… continuing anyways”, strerror(errno));
}
if (nm->start()) {//创建用于接收kernel的socket,实例化NetlinkHandler以及父类实例,开启socket检测
SLOGE(“Unable to start NetlinkManager (%s)”, strerror(errno));
exit(1);
}
coldboot(“/sys/block”);//遍历所有设备信息,全部发送一个add 的uevent
// coldboot(“/sys/class/switch”);
/*
* Now that we’re up, we can respond to commands
*/
if (cl->startListener()) {//开启vold 的socket以及检测
SLOGE(“Unable to start CommandListener (%s)”, strerror(errno));
exit(1);
}
// Eventually we’ll become the monitoring thread
while(1) {
sleep(1000);
}
SLOGI(“Vold exiting”);
exit(0);
}
VolumeManager 作为Volume的管理类, CommandListener 作为命令注册监听执行相关的类,NetlinkManager 作为接收kernel uevent事件的类
Vold的主体结构大体就是这样,往后依次分析各个功能细节以及关联!
原文:http://blog.csdn.net/jscese/article/details/38068441