标签:netlink socket 虚函数 uevent handleblockevent
在前文Android—— 4.2 Vold挂载管理_主体构建main (一)中有结构图表示,Vold是kernel与用户层的一个交互管理模块,
Android—— 4.2 Vold挂载管理_VolumeManager (三) 简单介绍了核心VolumeManager的构建,这篇分析从kernel进程沟通到VolumeManager进程的关键:NetlinkManager
撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/38586021
依旧从/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; }
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(int listenerSocket) : NetlinkListener(listenerSocket) { }
NetlinkListener::NetlinkListener(int socket) : SocketListener(socket, false) { mFormat = NETLINK_FORMAT_ASCII; }
接着调用的start()函数,也是最终实现在SockListener的startListener()。
继承关系:NetlinkHandler——>NetlinkListener——>SocketListener
关于构造SockListener以及startListener()函数开启socket监听的实现流程在前文Android—— 4.2 Vold挂载管理_CommandListener (二)
中已分析,
区别在于socket不同,而且不是正常监听的socket,这里的mListen为false,CommandListener的为true,不再做分析!
当监听到了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; }
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 } }
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 } }
画了一张NetlinkManager部分大体的功能结构图:
整个NetlinkManager部分的实现大体就是这样,至于kernel层如果检测到存储设备的热插拔发出uevent的以及Volume的处理后续分析!
Android—— 4.2 Vold挂载管理_NetlinkManager (四),布布扣,bubuko.com
Android—— 4.2 Vold挂载管理_NetlinkManager (四)
标签:netlink socket 虚函数 uevent handleblockevent
原文地址:http://blog.csdn.net/jscese/article/details/38586021