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

android /system/vold源码分析(5)

2016-06-10 22:43 513 查看
CommandListener
继承关系:
SocketListener ---> FrameworkListener ---> CommandListener
对比NetlinkHandle的继承关系:
SocketListener ---> NetlinkListener ---> NetlinkHandler

nm->start()执行流程
(1)nm->start() 即 NetlinkManager::start()
(2)调用NetlinkHandler::start()
(3)调用SocketListener::startListener()

CommandListener:: startListener ()
当执行CommandListener:: startListener ()时,它的调用即是调用SocketListener::startListener()。但二者使用的socket不同,NetlinkHandler在调用前创建了一个socket,但CommandListener在SocketListener::startListener()中通过调用android_get_control_socket(mSocketName)获得socket,相关代码如下:

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);
}

SocketListener有两个构造函数,
SocketListener::SocketListener(int socketFd, bool listen) {
init(NULL, socketFd, listen, false);
}

SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) {
init(socketName, -1, listen, useCmdNum);
}

NetlinkHandler在构造时使用的是第一个,它直接指定了socketFd,并且指定socketName为NULL:
mHandler = new NetlinkHandler(mSock); //代码在NetlinkManager::start()中

NetlinkHandler::NetlinkHandler(int listenerSocket) :
NetlinkListener(listenerSocket) {
}
//父类NetlinkListener的构造函数
NetlinkListener::NetlinkListener(int socket) :
SocketListener(socket, false) {
mFormat = NETLINK_FORMAT_ASCII;
}

CommandListener在构造时使用的是第二个,它指定了socketName,但没有指定socketFd:
CommandListener::CommandListener() :
FrameworkListener("vold", true) {
registerCmd(new DumpCmd());
registerCmd(new VolumeCmd());
registerCmd(new AsecCmd());
registerCmd(new ObbCmd());
registerCmd(new StorageCmd());
registerCmd(new XwarpCmd());
registerCmd(new CryptfsCmd());
registerCmd(new FstrimCmd());
}

FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :
SocketListener(socketName, true, withSeq) {
init(socketName, withSeq);
}

再回到android_get_control_socket函数,这里的参数是上面构造函数指定的“vold”,此函数的代码在socket.h中:
/*
* android_get_control_socket - simple helper function to get the file
* descriptor of our init-managed Unix domain socket. `name' is the name of the
* socket, as given in init.rc. Returns -1 on error.
*
* This is inline and not in libcutils proper because we want to use this in
* third-party daemons with minimal modification.
*/
static inline int android_get_control_socket(const char *name)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
const char *val;
int fd;

/* build our environment variable, counting cycles like a wolf ... */
#if HAVE_STRLCPY
strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
#else	/* for the host, which may lack the almightly strncpy ... */
strncpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
key[sizeof(key)-1] = '\0';
#endif

val = getenv(key);
if (!val)
return -1;

errno = 0;
fd = strtol(val, NULL, 10);
if (errno)
return -1;

return fd;
}

根据参数mSocketName, 加上前缀ANDROID_SOCKET_,即字符串ANDROID_SOCKET_vold,调用getenv获取到相应socket的文件描述符。vold会在init.rc中创建这个socket:
service vold /system/bin/vold
class core
socket vold stream 0660 root mount
ioprio be 2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: