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

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值