在前文Android—— 4.2 Vold挂载管理_主体构建main (一)中有结构图表示,Vold是kernel与用户层的一个交互管理模块。

Android—— 4.2 Vold挂载管理_VolumeManager (三)简介了核心VolumeManager的构建。这篇分析从kernel进程沟通到VolumeManager进程的关键:NetlinkManager

撰写不易。转载请注明出处:http://blog.csdn.net/jscese/article/details/38586021

一:NetlinkManager构建

依然从/system/vold/main.cpp中的main中:

    if (!(nm = NetlinkManager::Instance())) {
SLOGE("Unable to create NetlinkManager");
exit(1);
}; ... if (nm->start()) {
SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));
exit(1);
}

构造函数没干啥。基本的构建由这个 start 函数開始

/system/vold/NetlinkManager.cpp中:

int NetlinkManager::start() {
struct sockaddr_nl nladdr;//使用的 socket 结构 用于与kernel进程通信 
int sz = 64 * 1024;
int on = 1; memset(&nladdr, 0, sizeof(nladdr));// 初始化
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = 0xffffffff; if ((mSock = socket(PF_NETLINK,//创建 类型为 PF_NETLINK
SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
SLOGE("Unable to create uevent socket: %s", strerror(errno));
return -1;
} if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {//配置大小
SLOGE("Unable to set uevent socket SO_RECBUFFORCE option: %s", strerror(errno));
return -1;
} if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));
return -1;
} if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {//绑定socket地址
SLOGE("Unable to bind uevent socket: %s", strerror(errno));
return -1;
} mHandler = new NetlinkHandler(mSock);//传入创建的socket的标识构造一个NetlinkHandler实例
if (mHandler->start()) {//开启socket监控
SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));
return -1;
}
return 0;
}

这里使用的是Netlink套接字。Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最经常使用的接口。结构定义:

struct sockaddr_nl {
__kernel_sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
__u32 nl_pid; /* port ID */
__u32 nl_groups; /* multicast groups mask */
};

看NetlinkHandler的构造:

NetlinkHandler::NetlinkHandler(int listenerSocket) :
NetlinkListener(listenerSocket) {
}

跟着父类:

NetlinkListener::NetlinkListener(int socket) :
SocketListener(socket, false) {
mFormat = NETLINK_FORMAT_ASCII;
}

这里又是构造了一个SockListener的实例,传入了上面创建的socket标识。

接着调用的start()函数,也是终于实如今SockListener的startListener()。

继承关系:NetlinkHandler——>NetlinkListener——>SocketListener

关于构造SockListener以及startListener()函数开启socket监听的实现流程在前文Android—— 4.2 Vold挂载管理_CommandListener (二)中已分析,

差别在于socket不同。并且不是正常监听的socket,这里的mListen为false,CommandListener的为true。不再做分析!

二:NetlinkManager实现:

当监听到了socket事件的时候,同CommandListener一样,调用当时SocketListener实例的虚函数onDataAvailable的子类中的实现

这里是system/core/libsysutils/src/NetlinkListener.cpp中:

bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
int socket = cli->getSocket();
ssize_t count;
uid_t uid = -1; count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv(
socket, mBuffer, sizeof(mBuffer), &uid));//从socket中抽取出event的buffer
if (count < 0) {
if (uid > 0)
LOG_EVENT_INT(65537, uid);
SLOGE("recvmsg failed (%s)", strerror(errno));
return false;
} NetlinkEvent *evt = new NetlinkEvent();
if (!evt->decode(mBuffer, count, mFormat)) {//交给NetlinkEent 实例解析buffer,保存參数
SLOGE("Error decoding NetlinkEvent");
} else {
onEvent(evt);//虚函数~传递evt给子类NetlinkHandler实现
} delete evt;
return true;
}

到NetlinkHandler.cpp中:

void NetlinkHandler::onEvent(NetlinkEvent *evt) {
VolumeManager *vm = VolumeManager::Instance();
const char *subsys = evt->getSubsystem(); if (!subsys) {
SLOGW("No subsystem found in netlink event");
return;
} if (!strcmp(subsys, "block")) {
vm->handleBlockEvent(evt);//把event事件交给VolumeManager
}
}

这里真正传递到了VolumeManager中,实现了从kernel到vold,看下VolumeManager的handle处理:

void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
const char *devpath = evt->findParam("DEVPATH"); /* Lookup a volume to handle this device */
VolumeCollection::iterator it;
bool hit = false;
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {//遍历容器中的Volume 实例依次传入event
if (!(*it)->handleBlockEvent(evt)) {//Volume类的虚函数。子类DirectVolume实现
#ifdef NETLINK_DEBUG
SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
#endif
hit = true;
break;
}
} if (!hit) {
#ifdef NETLINK_DEBUG
SLOGW("No volumes handled block event for '%s'", devpath);
#endif
}
}

能够看到这里用到了Android—— 4.2 Vold挂载管理_VolumeManager (三)中解析出来增加进Volume容器中的Volume。

画了一张NetlinkManager部分大体的功能结构图:

整个NetlinkManager部分的实现大体就是这样,至于kernel层假设检測到存储设备的热插拔发出uevent的以及Volume的处理兴许分析!

Android—— 4.2 Vold挂载管理_NetlinkManager (四)的更多相关文章

  1. android中退出当前应用程序的四种方法

    android中退出当前应用程序的四种方法 [IT168 技术]Android程序有很多Activity,比如说主窗口A,调用了子窗口B,如果在B中直接finish(), 接下里显示的是A.在B中如何 ...

  2. Linux 挂载管理(mount)

    标签:mount,umount 概述 在上一章增加linux操作系统空间中已经使用过了mount命令对分区进行挂载,这一章详细介绍挂载管理,该命令涉及的知识点也挺多的而且也还比较重要,是需要掌握的一个 ...

  3. android的Log日志打印管理工具类(一)

    android的Log日志的打印管理工具类: package com.gzcivil.utils; import android.util.Log; /** * 日志打印管理 * * @author ...

  4. 使用Visual Studio Team Services敏捷规划和项目组合管理(四)——冲刺计划和任务板

    使用Visual Studio Team Services敏捷规划和项目组合管理(四)--冲刺计划和任务板 团队在sprint计划会议期间创建冲刺积压工作项,通常在冲刺的第一天召开该会议.每个冲刺都对 ...

  5. Spring事务管理的四种方式(以银行转账为例)

    Spring事务管理的四种方式(以银行转账为例) 一.事务的作用 将若干的数据库操作作为一个整体控制,一起成功或一起失败.   原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不 ...

  6. Android 仿今日头条频道管理(下)(GridView之间Item的移动和拖拽)

    前言 上篇博客我们说到了今日头条频道管理的操作交互体验,我也介绍了2个GridView之间Item的相互移动.详情请參考:Android 仿今日头条频道管理(上)(GridView之间Item的移动和 ...

  7. Android UI组件:布局管理器

    为了更好的管理Android应用的用户界面中的组件,Android提供了布局管理器.通过使用布局管理器,Android应用的图形用户界面具有良好的平台无关性.通常,推荐使用布局管理器来管理组件的分布. ...

  8. Android 6.0 - 动态权限管理的解决方案(转)

    转自:http://www.cnblogs.com/dubo-/p/6018262.html Android 6.0 - 动态权限管理的解决方案   转载请标注 Android 6.0版本(Api 2 ...

  9. android中常用的布局管理器(二)

    接上篇博客 (3)LinearLayout     线性布局管理器 线性布局管理器是将放入其中的组件按照垂直或水平方向来布局,每一行或每一列只能放一个组件,并且不会换行,当组件排列到窗体的边缘后,后面 ...

随机推荐

  1. Scala不使用null 而使用Option,None,Some的好处

    刚接触Scala时就很奇怪, 为什么Java已经有null了,却偏偏还要弄出个None 后来依然我行我素在Scala里使用null, 结果就是经常被NullPointerException折磨得阴魂不 ...

  2. PHP json_encode 转换成空对象和空数组

    对于以下对象 $foo = array( "bar1" => array(), "bar2" => array() ); 我想转换成 { " ...

  3. Android 设置图片倒影效果

    首先,贴出效果图: 1.布局文件main.xml <?xml version="1.0" encoding="utf-8"?> <Linear ...

  4. Cryptography I 学习笔记 --- 密钥交换

    1. 使用可信第三方(Trusted third parties)进行密钥交换. a. Alice与TTP之间的密钥是K1,Bob与TTP之间的密钥是K2. b. Alice向TTP发起一个与Bob交 ...

  5. BZOJ 4543 2016北京集训测试赛(二)Problem B: thr 既 长链剖分学习笔记

    Solution 这题的解法很妙啊... 考虑这三个点可能的形态: 令它们的重心为距离到这三个点都相同的节点, 则其中两个点分别在重心的两棵子树中, 且到重心的距离相等; 第三个点可能在重心的一棵不同 ...

  6. JavaScript 深克隆

    深克隆 function judgeType(arg){//判断js数据类型 return Object.prototype.toString.call(arg).slice(8,-1); } fun ...

  7. Linux ClientDataSet libmidas.so.2

    Linux ClientDataSet libmidas.so.2 DELPHI LINUX程序使用CLIENTDATASET控件,部署的时候需要libmidas.so,相当于WINDOWS程序的MI ...

  8. Fresco的使用及注意事项

    Fresco的使用及注意事项 时间 2016-10-17 18:32:12 DevWiki's Blog 原文  http://blog.devwiki.net/index.php/2016/10/1 ...

  9. Error Code: 1055 incompatible with sql_mode=only_full_group_by

    OperationalError at / (1055, "Expression #1 of ORDER BY clause is not in GROUP BY clause and co ...

  10. Testin云測手游质量管家 七大兵器助CP称霸江湖

    Testin云測手游质量管家 七大兵器助CP称霸江湖 2014/09/29 · Testin · 产品评測 在武侠江湖里,高手不须要武功高强.亦要具备厉害的武器.有人的地方就有江湖.手游行业相同腥风血 ...