Android vold启下篇(NetlinkHandler)
来源:互联网 发布:汽车pp2000软件下载 编辑:程序博客网 时间:2024/06/05 05:41
在文章Android Vold实现总览中我们以代码和数据流图的方式介绍了vold的整个主流程。
而这篇文章主要分析vold贴近底层内核的代码,所以在文章标题中有启下两个字。在这里为方便引出相关代码,我们再次贴上主流程的代码:
int main() { VolumeManager *vm; //管理volume CommandListener *cl;//和Framework进行通讯 NetlinkManager *nm;//接收内核消息 SLOGI("Vold 2.1 (the revenge) firing up"); mkdir("/dev/block/vold", 0755);//创建设备节点 /* For when cryptfs checks and mounts an encrypted filesystem */ klog_set_level(6); /* 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(); vm->setBroadcaster((SocketListener *) cl); nm->setBroadcaster((SocketListener *) cl); if (vm->start()) {//啥也没干 SLOGE("Unable to start VolumeManager (%s)", strerror(errno)); exit(1); } if (process_config(vm)) {//根据配置文件/etc/vold.fstab,初始化VolumeManager SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno)); } if (nm->start()) {//启动内核监听 SLOGE("Unable to start NetlinkManager (%s)", strerror(errno)); exit(1); } coldboot("/sys/block");//触发内核sysfs发送uevent事件 // coldboot("/sys/class/switch"); /* * Now that we're up, we can respond to commands */ if (cl->startListener()) {//启动对Framework的监听 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); }
第5行的NetlinkManager的nm变量及相关操作,就是我们在本章要研究的问题。
一、由NetlinkManager开启整个过程
1.1、在上面的代码中,我们可以看到有关键代码:nm->start();进入到该函数,有如下两段关键代码:
if ((mSock = socket(PF_NETLINK, SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) { SLOGE("Unable to create uevent socket: %s", strerror(errno)); return -1; }
mHandler = new NetlinkHandler(mSock); if (mHandler->start()) { SLOGE("Unable to start NetlinkHandler: %s", strerror(errno)); goto out; }第一段代码创建了以PF_NETLINK标识的socket,第二段代码以该socket创建了NetlinkHandler对象;
1.2、关于NetlinkHandler
NetlinkHandler::NetlinkHandler(int listenerSocket) : NetlinkListener(listenerSocket) {}NetlinkHandler::~NetlinkHandler() {}int NetlinkHandler::start() { return this->startListener();}int NetlinkHandler::stop() { return this->stopListener();}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); }}由以上代码可知,NetlinkHandler的start函数调用了父类函数的 startListener,启动了对内核的监听,并实现了父类的onEvent函数。
1.3、关于NetlinkListener,如下:
NetlinkListener::NetlinkListener(int socket) : SocketListener(socket, false) { mFormat = NETLINK_FORMAT_ASCII;}#endifNetlinkListener::NetlinkListener(int socket, int format) : SocketListener(socket, false), mFormat(format) {}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)); 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)) { SLOGE("Error decoding NetlinkEvent"); } else { onEvent(evt); } delete evt; return true;}由上可知NetlinkListener继承自SocketListener,1.2节中NetlinkHandler的start函数调用的startListener函数正是在此类中实现,如下:
int SocketListener::startListener() { if (!mSocketName && mSock == -1) { SLOGE("Failed to start unbound listener"); errno = EINVAL; return -1; } else if (mSocketName) { if ((mSock = android_get_control_socket(mSocketName)) < 0) { SLOGE("Obtaining file descriptor socket '%s' failed: %s", mSocketName, strerror(errno)); return -1; } SLOGV("got mSock = %d for %s", mSock, mSocketName); } if (mListen && listen(mSock, 4) < 0) { SLOGE("Unable to listen on socket (%s)", strerror(errno)); return -1; } else if (!mListen) mClients->push_back(new SocketClient(mSock, false, mUseCmdNum)); if (pipe(mCtrlPipe)) { SLOGE("pipe failed (%s)", strerror(errno)); return -1; } if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) { SLOGE("pthread_create (%s)", strerror(errno)); return -1; } return 0;}该函数中的套接字mSock是在2.1中创建并通过构造函数参数的方式传递到了SocketListener类中。
在startListener函数中,有创建一个threadStart线程,该函数的实现如下:
void *SocketListener::threadStart(void *obj) { SocketListener *me = reinterpret_cast<SocketListener *>(obj); me->runListener(); pthread_exit(NULL); return NULL;}该函数中调用了SocketListener的runListener函数,而该函数正是接收硬件消息的地方,代码太多,截取关键部分如下:
while (!pendingList->empty()) { /* Pop the first item from the list */ it = pendingList->begin(); SocketClient* c = *it; pendingList->erase(it); /* Process it, if false is returned and our sockets are * connection-based, remove and destroy it */ if (!onDataAvailable(c) && mListen) { /* Remove the client from our array */ SLOGV("going to zap %d for %s", c->getSocket(), mSocketName); pthread_mutex_lock(&mClientsLock); for (it = mClients->begin(); it != mClients->end(); ++it) { if (*it == c) { mClients->erase(it); break; } } pthread_mutex_unlock(&mClientsLock); /* Remove our reference to the client */ c->decRef(); } } }该函数中将收到信息的SocketClient对象指针传递到了onDataAvailable函数中,这样流程跑到了2.3节中的第一段代码的NetlinkListener::onDataAvailable函数,
该函数中,有如下两段关键代码:
count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv( socket, mBuffer, sizeof(mBuffer), &uid));
onEvent(evt);第一段代码是从socket中读取linux内核发来的消息;
第二段是将消息传递到onEvent函数,该onEvent函数我们在2.2节中贴出来了,通过代码可知,消息传递到了VolumeManager中。
关于vold和linux内核交互已经结束,下篇讲解消息传递到VolumeManager中的处理过程。
0 0
- Android vold启下篇(NetlinkHandler)
- android vold:图解VOLD
- Android VOLD
- Android vold
- android vold
- Android Vold
- ANDROID中的VOLD分析
- Android vold浅析
- Android VOLD 分析
- Vold 2.0 ---- Android-2.3
- android 2.2 vold
- Android 2.1 Vold 分析
- Android Vold架构
- ANDROID中的VOLD分析
- Android Vold 分析
- ANDROID中的VOLD分析
- ANDROID中的VOLD分析
- Android Vold架构
- AFNetworking下载进度条显示
- Java编译原理(有感)
- cookie与session机制
- ios - cordova 简介
- 算法导论-第二章
- Android vold启下篇(NetlinkHandler)
- iOS保存图片视频到photoLibrary
- 选择排序
- STL---string和char
- 关于grep和egrep的一些整理
- python编写的一个日历 签到中可用
- 如何加快Android Studio 编译app 的速度
- Android 下拉展开动画
- JVM运行过程