您的位置:首页 > 移动开发 > Android开发

Android vold启下篇(NetlinkHandler)

2016-06-28 15:37 399 查看
在文章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;
}
#endif

NetlinkListener::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中的处理过程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息