android 存储系统,Android的存储系统—Vold与MountService分析(二)
Android的存储系统(二)回顾:【源码分析】1. Vold的main函数Vold也是通过init进程启动,它在init.rc中的定义如下:1 service vold /system/bin/vold2classcore3socket vold stream 0660root mount4ioprio be 2Vold服务放到了core分组,这就意味着系统启动时,...
Android的存储系统(二)
回顾:
【源码分析】
1. Vold的main函数
Vold也是通过init进程启动,它在init.rc中的定义如下:
1 service vold /system/bin/vold2 classcore3 socket vold stream 0660root mount4 ioprio be 2
Vold服务放到了core分组,这就意味着系统启动时,它就会被init进程启动。这里定义的一个socket,主要用语Vold和Java层的MountService通信。
Vold模块的源代码位于system/vold,我们看看入口函数main(),代码如下:
1 intmain() {
2 VolumeManager*vm;
3 CommandListener*cl;
4 NetlinkManager*nm;
5
6 SLOGI("Vold 2.1 (the revenge) firing up");
7
8 mkdir("/dev/block/vold", 0755); // 创建vold目录
9
10 klog_set_level(6);
11
12if (!(vm =VolumeManager::Instance())) { // 创建VolumeManager对象
13 exit(1);
14 };
15
16if (!(nm =NetlinkManager::Instance())) { // 创建NetlinkManager对象
17 exit(1);
18 };
19
22 cl= newCommandListener(); // 创建CommandListener对象
23 vm->setBroadcaster((SocketListener *) cl); // 建立vm和cl的联系
24 nm->setBroadcaster((SocketListener *) cl); // 建立nm和cl的联系
25
26if (vm->start()) { // 启动VolumeManager
27 exit(1);
28 }
29
30if(process_config(vm)) { // 创建文件/fstab.xxx中定义的Volume对象
31 SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
32 }
33
34 cryptfs_pfe_boot();
35
36if (nm->start()) { // 启动NetlinkManager,会调用NetlinkManager的start()方法,它创建PF_NETLINK socket,并开启线程从此socket中读取数据
37 exit(1);
38 }
39
40 coldboot("/sys/block"); // 冷启动,创建/sys/block下的节点文件
41
42if (cl->startListener()) { // 开始监听Framework的socket
43 exit(1);
44 }
45
46while(1) { // 进入循环
47 sleep(1000); // 主线程进入休眠
48 }
49
50 SLOGI("Vold exiting");
51 exit(0);
52 }
main函数的主要工作是创建3个对象:VolumeManager、NetlinkManager和CommandListener,同时将CommandListener对象分别设置到了VolumeManager对象和NetlinkManager对象中。
从前贴的架构图中可以发现,CommandListener对象用于和Java层的NativeDaemonConnector对象进行socket通信,因此,无论是VolumeManager对象还是NetlinkManager对象都需要拥有CommandListener对象的引用。
2. 监听驱动发出的消息—Vold的NetlinkManager对象
NetlinkManager对象的主要工作是监听驱动发出的uevent消息。
main()函数中调用NetlinkManager类的静态函数Instance()来创建NetlinkManager对象,代码如下:
1 NetlinkManager *NetlinkManager::Instance() {2 if (!sInstance)3 sInstance = newNetlinkManager(); // NetlinkManager对象通过静态变量sInstance来引用,这意味着vold进程中只有一个NetlinkManager对象。4 returnsInstance;5 }
看下NetlinkManager的构造函数,代码如下:
1 NetlinkManager::NetlinkManager() {2 mBroadcaster =NULL;3 }
NetlinkManager的构造函数只是对mBroadcaster进行了初始化。我们可以发现main()函数中通过调用NetlinkManager的setBroadcaster()函数来给变量mBroadcaster重新赋值。
nm->setBroadcaster((SocketListener *) cl);
main()函数还调用了NetlinkManager的start()函数,我们观察一下NetlinkManager中的start()方法,代码如下:
1 intNetlinkManager::start() {2 structsockaddr_nl nladdr;3 int sz = 64 * 1024;4 int on = 1;5
6 memset(&nladdr, 0, sizeof(nladdr));7 nladdr.nl_family =AF_NETLINK;8 nladdr.nl_pid =getpid();9 nladdr.nl_groups = 0xffffffff;10 /*创建一个socket用于内核空间和用户空间的异步通信,监控系统的hotplug事件*/
11 if ((mSock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {12 SLOGE("Unable to create uevent socket: %s", strerror(errno));13 return -1;14 }15 /*设置缓冲区大小为64KB*/
16 if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {17 SLOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno));18 goto out;19 }20 /*设置允许 SCM_CREDENTIALS 控制消息的接收*/
21 if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {22 SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));23 goto out;24 }25 /*绑定 socket 地址*/
26 if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {27 SLOGE("Unable to bind uevent socket: %s", strerror(errno));28 goto out;29 }30 /*利用新创建的socket实例化一个NetlinkHandler类对象用于监听socket,NetlinkHandler继承了类NetlinkListener,NetlinkListener又继承了类SocketListener*/
31 mHandler = newNetlinkHandler(mSock);32 if (mHandler->start()) { // 启动NetlinkHandler,调用NetlinkHandler的start()函数33 SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));34 goto out;35 }36
37 return 0;38
39 out:40 close(mSock);41 return -1;42 }
我们看一下NetlinkManager的家族关系,如下图:
上面的虚线为启动时的调用流程:
(1) class NetlinkManager(在其start函数中创建了NetlinkHandler对象,并把创建的socket作为参数)
(2)class NetlinkHandler: public NetlinkListener(实现了onEvent)
(3) class NetlinkListener : public SocketListener(实现了onDataAvailable)
(4) class SocketListener(实现了runListener,在一个线程中通过select查看哪些socket有数据,通过调用onDataAvailable来读取数据)。
总结:此贴主要分析了Vold的main()函数和NetlinkManager对象的源码,通过源码了解对象的创建时机和函数调用流程,下一贴会继续从NetlinkHandler的start()方法深入分析,继续源码的学习,很快会与大家见面,欢迎大家批评指正,我们互相学习。
更多推荐
所有评论(0)