转自:http://blog.csdn.net/new_abc/article/details/7396733

流程图:


vold启动在init.rc中:

service vold /system/bin/vold    socket vold stream 0660 root mount    ioprio be 2
注意这里创建了一个socket,用于vold和FrameWork层通信

vold代码在system/vold目录下面,函数入口main函数:

int main() {    VolumeManager *vm;    CommandListener *cl;    NetlinkManager *nm;    SLOGI("Vold 2.1 (the revenge) firing up");    mkdir("/dev/block/vold", 0755);
这里建立了一个/dev/block/vold目录用于放置后面建立的vold节点

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

这里创建了VolumeManager和NetlinkManager两个实例,VolumeManager主要负责Voluem的一些管理,NetlinkManager主要负责管理与内核之间的通信

    cl = new CommandListener();
这里首先创建了CommandListener,CommandListener主要负责与FrameWork层的通信,处理从FrameWork层收到的各种命令,我们先看看他的构造函数:

CommandListener::CommandListener() :                 FrameworkListener("vold") {    registerCmd(new DumpCmd());    registerCmd(new VolumeCmd());    registerCmd(new AsecCmd());    registerCmd(new ObbCmd());    registerCmd(new ShareCmd());    registerCmd(new StorageCmd());    registerCmd(new XwarpCmd());}
这里注册了各种命令,注意 FrameworkListener("vold"),FrameworkListener又继承了SocketListener,最终"vold"传到了SocketListener里面。

    vm->setBroadcaster((SocketListener *) cl);    nm->setBroadcaster((SocketListener *) cl);
    if (vm->start()) {    SLOGE("Unable to start VolumeManager (%s)", strerror(errno));    exit(1);  }

设置了Broadcaster,后面给FrameWork层发送消息就跟它有关了,

if (process_config(vm)) {        SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));    }
解析vold.fstab,我们看下process_config函数:

static int process_config(VolumeManager *vm){    FILE *fp;    int n = 0;    char line[255];    if (!(fp = fopen("/etc/vold.fstab", "r"))) {        return -1;    }    while(fgets(line, sizeof(line), fp)) {        char *next = line;        char *type, *label, *mount_point;        n++;        line[strlen(line)-1] = '\0';        if (line[0] == '#' || line[0] == '\0')            continue;        if (!(type = strsep(&next, " \t"))) {            SLOGE("Error parsing type");            goto out_syntax;        }        if (!(label = strsep(&next, " \t"))) {//标签            SLOGE("Error parsing label");            goto out_syntax;        }        if (!(mount_point = strsep(&next, " \t"))) {//挂载点            SLOGE("Error parsing mount point");            goto out_syntax;        }        if (!strcmp(type, "dev_mount")) {//挂载命令            DirectVolume *dv = NULL;            char *part, *sysfs_path;            if (!(part = strsep(&next, " \t"))) {//分区数                SLOGE("Error parsing partition");                goto out_syntax;            }            if (strcmp(part, "auto") && atoi(part) == 0) {//auto则表示只有1个子分区                SLOGE("Partition must either be 'auto' or 1 based index instead of '%s'", part);                goto out_syntax;            }            if (!strcmp(part, "auto")) {                dv = new DirectVolume(vm, label, mount_point, -1);            } else {                dv = new DirectVolume(vm, label, mount_point, atoi(part));            }            while((sysfs_path = strsep(&next, " \t"))) {                if (dv->addPath(sysfs_path)) {//这里的Path在挂载的时候会用到                    SLOGE("Failed to add devpath %s to volume %s", sysfs_path,                         label);                    goto out_fail;                }            }            vm->addVolume(dv);//添加到VolumeManager,由它负责统一管理        } else if (!strcmp(type, "map_mount")) {        } else {            SLOGE("Unknown type '%s'", type);            goto out_syntax;        }    }    fclose(fp);    return 0;out_syntax:    SLOGE("Syntax error on config line %d", n);    errno = -EINVAL;out_fail:    fclose(fp);    return -1;   }

解析了vold.fstab之后 ,就开始启动NetlinkManager,

if (nm->start()) {        SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));        exit(1);    }
我们跟进去看看:

int NetlinkManager::start() {    struct sockaddr_nl nladdr;    int sz = 64 * 1024;     int on = 1;    memset(&nladdr, 0, sizeof(nladdr));    nladdr.nl_family = AF_NETLINK;    nladdr.nl_pid = getpid();    nladdr.nl_groups = 0xffffffff;    if ((mSock = socket(PF_NETLINK,                        SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {//注册UEVENT事件,用于接收内核消息        SLOGE("Unable to create uevent socket: %s", strerror(errno));        return -1;    }    if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {        SLOGE("Unable to set uevent socket options: %s", strerror(errno));        return -1;    }    if (setsockopt(mSock, SOL_SOCKET, SO_REUSEADDR,  &on, sizeof(on)) < 0) {        LOGE("Unable to set SO_REUSEADDR options: %s", strerror(errno));        return -1;    }    if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {        SLOGE("Unable to bind uevent socket: %s", strerror(errno));        return -1;    }    mHandler = new NetlinkHandler(mSock);//NetlinkHandler用于对接收到的内核消息进行处理    if (mHandler->start()) {//开始监听内核消息        SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));        return -1;    }    return 0;}

我们跟进mHandler->start()最终调用SocketListener::startListener()

int SocketListener::startListener() {    if (!mSocketName && mSock == -1) { //这里mSock 刚赋值了        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;        }    }    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));    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;}
我们再看下threadStart,最终调用runListener

void SocketListener::runListener() {    while(1) {        SocketClientCollection::iterator it;        fd_set read_fds;        int rc = 0;        int max = 0;        FD_ZERO(&read_fds);        if (mListen) {            max = mSock;            FD_SET(mSock, &read_fds);        }        FD_SET(mCtrlPipe[0], &read_fds);  //把mCtrlPipe[0]也加入监听中        if (mCtrlPipe[0] > max)            max = mCtrlPipe[0];        pthread_mutex_lock(&mClientsLock);        for (it = mClients->begin(); it != mClients->end(); ++it) {            FD_SET((*it)->getSocket(), &read_fds);            if ((*it)->getSocket() > max)                max = (*it)->getSocket();        }        pthread_mutex_unlock(&mClientsLock);        if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {//阻塞直到有数据到来            SLOGE("select failed (%s)", strerror(errno));            sleep(1);            continue;        } else if (!rc)            continue;        if (FD_ISSET(mCtrlPipe[0], &read_fds))//mCtrlPipe[0]有数据,则结循环,注意是在stopListener的时候 往mCtrlPipe[1]写数据            break;        if (mListen && FD_ISSET(mSock, &read_fds)) {            struct sockaddr addr;            socklen_t alen = sizeof(addr);            int c;            if ((c = accept(mSock, &addr, &alen)) < 0) {//有新的连接来了,主要是FrameWork层的,                SLOGE("accept failed (%s)", strerror(errno));                sleep(1);                continue;            }            pthread_mutex_lock(&mClientsLock);            mClients->push_back(new SocketClient(c));//加到监听的列表            pthread_mutex_unlock(&mClientsLock);        }        do {            pthread_mutex_lock(&mClientsLock);            for (it = mClients->begin(); it != mClients->end(); ++it) {                int fd = (*it)->getSocket();                if (FD_ISSET(fd, &read_fds)) {                    pthread_mutex_unlock(&mClientsLock);                    if (!onDataAvailable(*it)) {//处理消息                        close(fd);                        pthread_mutex_lock(&mClientsLock);                        delete *it;                        it = mClients->erase(it);                        pthread_mutex_unlock(&mClientsLock);                    }                    FD_CLR(fd, &read_fds);                    pthread_mutex_lock(&mClientsLock);                    continue;                }            }            pthread_mutex_unlock(&mClientsLock);        } while (0);    }}

这样,就开始了监听来自内核的事件

    coldboot("/sys/block");//    coldboot("/sys/class/switch");    /*     * Now that we're up, we can respond to commands     */    if (cl->startListener()) {        SLOGE("Unable to start CommandListener (%s)", strerror(errno));        exit(1);    }
这里主要看cl->startListener,也跟前面 的一样,调用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;        }    }

这里mSocketName 为"vold",mSock = -1,所以会调用android_get_control_socket,我们看下这个函数
/* * 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;}

这里面通过组合成一个环境变量名,然后获取对应的值,那么这个值是什么时候设置的呢,我们看下系统初始化的时候调用的service_start
  
void service_start(struct service *svc, const char *dynamic_args){   ...   for (si = svc->sockets; si; si = si->next) {            int socket_type = (                    !strcmp(si->type, "stream") ? SOCK_STREAM :                        (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));            int s = create_socket(si->name, socket_type,                                  si->perm, si->uid, si->gid);            if (s >= 0) {                publish_socket(si->name, s);            }        }}

跟进publish_socket
  
static void publish_socket(const char *name, int fd){    char key[64] = ANDROID_SOCKET_ENV_PREFIX;    char val[64];    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,            name,            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));    snprintf(val, sizeof(val), "%d", fd);    add_environment(key, val);    /* make sure we don't close-on-exec */    fcntl(fd, F_SETFD, 0);}

没错,就是这里设置了这个环境变量的值。
  

Ok,到这里,vold基本就启动起来了,基本的通信环境也已经搭建好了,就等着u盘插入后kernel的消息的。。。。


以下博客写的比较详细,专业。

http://blog.csdn.net/gzshun/article/details/7172389

http://blog.csdn.net/gjsisi/article/details/7836446

http://www.rosoo.net/a/201209/16285.html

更多相关文章

  1. android 4.0 内核(3.0)编译方法
  2. Android中SensorManager.getRotationMatrix函数:计算出旋转矩阵,
  3. Android JNI(实现自己的JNI_OnLoad函数)
  4. 谷歌Android篡改Linux内核的真相
  5. Android中的Logcat方法查看内核的日志
  6. Android OpenGL库函数列表
  7. UML详解:解析Android消息处理机制:Handler/Thread/Looper & Messag
  8. Android仿QQ消息列表ListView滑动删除效果

随机推荐

  1. [置顶] Android的Activity屏幕切换动画(
  2. 【Android】android中Invalidate和postIn
  3. Android盈利模式,哪种更靠谱?
  4. 爱奇艺Android移动客户端app瘦身经验
  5. ANDROID深入研究和学习的课程
  6. Android仿人人客户端(v5.7.1)——欢迎和导
  7. Android软键盘-弹起时布局向上拉-多表单
  8. 关于 Android(安卓)程序员最近的状况
  9. Android的背景
  10. Android实现简易版弹钢琴效果