Android 7.0 存储系统—Vold与MountService分析(二)(转 Android 9.0 分析)
Android的存储系统(二)
|
回顾:前贴主要分析了Android存储系统的架构和原理图,简要的介绍了整个从Kernel-->Vold-->上层MountService之间的数据传输流程,在这样的基础上,我们开始今天的源码分析! |
【源码分析】
1. Vold的main函数
Vold也是通过init进程启动,它在init.rc中的定义如下:
service vold /system/bin/vold
class core
root mount
ioprio be
Vold服务放到了core分组,这就意味着系统启动时,它就会被init进程启动。这里定义的一个socket,主要用语Vold和Java层的MountService通信。
Vold模块的源代码位于system/vold,我们看看入口函数main(),代码如下:
1 int main() {
2 VolumeManager *vm;
3 CommandListener *cl;
4 NetlinkManager *nm;
5
6 SLOGI("Vold 2.1 (the revenge) firing up");
7
8 mkdir(); // 创建vold目录
9
10 klog_set_level();
11
12 if (!(vm = VolumeManager::Instance())) { // 创建VolumeManager对象
13 exit();
14 };
15
16 if (!(nm = NetlinkManager::Instance())) { // 创建NetlinkManager对象
17 exit();
18 };
19
22 cl = new CommandListener(); // 创建CommandListener对象
23 vm->setBroadcaster((SocketListener *) cl); // 建立vm和cl的联系
24 nm->setBroadcaster((SocketListener *) cl); // 建立nm和cl的联系
25
26 if (vm->start()) { // 启动VolumeManager
27 exit();
28 }
29
30 if (process_config(vm)) { // 创建文件/fstab.xxx中定义的Volume对象
31 SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
32 }
33
34 cryptfs_pfe_boot();
35
36 if (nm->start()) { // 启动NetlinkManager,会调用NetlinkManager的start()方法,它创建PF_NETLINK socket,并开启线程从此socket中读取数据
37 exit();
38 }
39
40 coldboot("/sys/block"); // 冷启动,创建/sys/block下的节点文件
41
42 if (cl->startListener()) { // 开始监听Framework的socket
43 exit();
44 }
45
46 ) { // 进入循环
47 sleep(); // 主线程进入休眠
48 }
4950 SLOGI("Vold exiting");
51 exit();
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对象,代码如下:
NetlinkManager *NetlinkManager::Instance() {
if (!sInstance)
sInstance = new NetlinkManager(); // NetlinkManager对象通过静态变量sInstance来引用,这意味着vold进程中只有一个NetlinkManager对象。
return sInstance;
}
看下NetlinkManager的构造函数,代码如下:
NetlinkManager::NetlinkManager() {
mBroadcaster = NULL;
}
NetlinkManager的构造函数只是对mBroadcaster进行了初始化。我们可以发现main()函数中通过调用NetlinkManager的setBroadcaster()函数来给变量mBroadcaster重新赋值。
nm->setBroadcaster((SocketListener *) cl);
main()函数还调用了NetlinkManager的start()函数,我们观察一下NetlinkManager中的start()方法,代码如下:
int NetlinkManager::start() {
struct sockaddr_nl nladdr;
* ;
;
memset(&nladdr, , sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = 0xffffffff;
/*创建一个socket用于内核空间和用户空间的异步通信,监控系统的hotplug事件*/
) {
SLOGE("Unable to create uevent socket: %s", strerror(errno));
;
}
/*设置缓冲区大小为64KB*/
) {
SLOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno));
goto out;
}
/*设置允许 SCM_CREDENTIALS 控制消息的接收*/
) {
SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));
goto out;
}
/*绑定 socket 地址*/
) {
SLOGE("Unable to bind uevent socket: %s", strerror(errno));
goto out;
}
/*利用新创建的socket实例化一个NetlinkHandler类对象用于监听socket,NetlinkHandler继承了类NetlinkListener,NetlinkListener又继承了类SocketListener*/
mHandler = new NetlinkHandler(mSock);
if (mHandler->start()) { // 启动NetlinkHandler,调用NetlinkHandler的start()函数
SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));
goto out;
}
;
out:
close(mSock);
;
}
我们看一下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()方法深入分析,继续源码的学习,很快会与大家见面,欢迎大家批评指正,我们互相学习。 |
Android 7.0 存储系统—Vold与MountService分析(二)(转 Android 9.0 分析)的更多相关文章
- Android 7.0 存储系统—Vold与MountService分析(三)(转 Android 9.0 分析)
Android的存储系统(三) 回顾:前帖分析了Vold的main()函数和NetlinkManager的函数调用流程,截止到NetlinkHandler的创建和start()调用,本帖继续分析源码 ...
- Android 7.0 存储系统—Vold与MountService分析(一)(转 Android 9.0 分析)
Android的存储系统(一) 看了很长时间Vold存储模块的相关知识,也死扣了一段时间的Android源码,发现Android存储系统所涉及的函数调用,以及Kernel与上层之间的Socket传输真 ...
- 【Android Studio安装部署系列】三十二、Android模拟器Genymotion安装使用教程详解
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 一.注册\登录 打开Genymotion官网,https://www.genymotion.com/ ,首先点击右上角的Sign in进行 ...
- [ipsec][strongswan] strongswan源码分析-- (二)rekey/reauth机制分析
目录 strongwan sa分析(二) 名词约定 rekey/reauth 机制分析 1 概述 2 reauth 3 CHILD SA rekey 4 IKE SA rekey 5 其他 stron ...
- 深入浅出 - Android系统移植与平台开发(十二)- Android JNI机制
第五章.JNI机制 4.1 JNI概述 由前面基础知识可知,Android的应用层由Java语言编写,Framework框架层则是由Java代码与C/C++语言实现,之所以由两种不同的语言组合开发框架 ...
- 【Android开发日记】之基础篇(二)——Android的动画效果
什么是动画,动画的本质是通过连续不断地显示若干图像来产生“动”起来的效果.比如说一个移动的动画,就是在一定的时间段内,以恰当的速率(起码要12帧/秒以上,才会让人产生动起来的错觉)每隔若干 ...
- 【Android Studio安装部署系列】四十二、Android Studio使用Eclipse中的keystore为App签名
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 从eclipse迁移到AndroidStudio,要用原Eclipse的签名文件,这样才能保证转到AndroidStudio后更新的 ...
- Android 7.0 启动篇 — init原理(二)(转 Android 9.0 分析)
======================================================== ================================== ...
- Activity的绘制流程简单分析(基于android 4.0源码进行分析)
要明白这个流程,我们还得从第一部开始,大家都知道 在activity里面 setcontentview 调用结束以后 就可以看到程序加载好我们的布局文件了,从而让我们在手机上看到这个画面. 那么我们来 ...
随机推荐
- FFPLAY的原理(二)
关于包Packets的注释 从技术上讲一个包可以包含部分或者其它的数据,但是ffmpeg的解释器保证了我们得到的包Packets包含的要么是完整的要么是多种完整的帧. 现在我们需要做的是让SaveFr ...
- IE的变态
1.它自身的内容动态调试功能太简陋. 2.另存成静态网页调试,发现网页代码和原先后台写的根本不一样,能稍微守点规矩行不?
- 关于.net 保存 decimal类型数据到SQLServer2012数据库时自动取整的问题
公司同事问我有没有遇到过decimal类型数据入库时,会自动取整的问题(比如12.3入库后值是12,12.8入库后值是13,入库后自动四舍五入自动取整): 之前就遇到过从数据去decimal类型数据时 ...
- Hbase出现ERROR: Can't get master address from ZooKeeper; znode data == null正确找到解决思路
第一次配置时出现这样的错误,也很懵的,到处上网找博客看资料,都试了个遍,但是问题还是存在,以下这些博客写的或许是解决一类问题的方式. https://blog.csdn.net/whbo111/art ...
- C++开发中BYTE类型数组转为对应的字符串
下午密码键盘返回了一个校验码,是BYTE类型数组,给上层应用返回最好是字符串方式,怎样原样的将BYTE数组转为string串呢?不多说,开动脑筋上手干!!! BYTE格式的数组bt{08,D7,B4, ...
- 定制炫彩界面:duilib与MFC 的对比
duilib是以DirectUI为技术原理开发的一款轻量级Windows桌面UI库,使用XML来描述界面风格,界面布局,可以很方便的构建高效,绚丽的,非常易于扩展的界面.从而很好的将界面和逻辑分离,同 ...
- 读《图解HTTP》有感-(HTTP首部)
写在前面 该章节是对请求报文及响应报文的首部信息进行解析.通过该章节的学习,相信大家对首部结构,及各个首部字段的作用有个基本的了解 正文 HTTP报文由HTTP报文首部.空行以及HTTP报文主体组成. ...
- Java公开课-05.log4j
log4j 一,log4j简介 1.如果程序中出现异常,我们怎么解决? 01.使用异常处理机制===>异常 (但是使用原则是,能不用异常处理机制,最好不用,怎么办?) 02.通过debug调试 ...
- 好代码是管出来的——使用Git来管理源代码
软件开发过程中一个重要的产出就是代码,软件的编码过程一般是由一个团队共同完成,它是一个并行活动,为了保证代码在多人开发中能够顺利完成,我们需要使用代码版本控制工具来对代码进行统一存储,并追踪每一份代码 ...
- 创建的UIWindow为何不显示
一.window创建方法不同,导致window的显示不同 1.window创建,但是不会显示 UIWindow *myWindow3 = [[UIWindow alloc] initWithFrame ...