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

来源:互联网 发布:db2数据库 编辑:程序博客网 时间:2024/05/29 19:05

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_STRLCPYstrlcpy(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';#endifval = 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
原创粉丝点击