Vold(volume Daemon),即Volume守护进程,用来管理Android中存储类的热拔插事件,处于Kernel和Framework之间,是两个层级连接的桥梁。先来看一下Vold在Android系统的整体架构。

该图主要包含了Framework和Vold进程的,Kernel和App层涉及的内容这里不再涉及,简单介绍一下。Vold主要是接收Kernel的uevent消息,然后通过NM(NetLinkManager)和VM(VolumeManager)处理,将消息传递到Framework的SM(StorageManager),最后SM会将数据存储下来,消息通知到在SM注册的服务和App。
 
Vold在系统中以守护进程存在,是一个单独的进程,首先来看下Vold的启动过程以及如何与Kernel和Framework建立的联系。
 
在init.rc中有start vold的命令会被init解析到,而start对应的函数do_start(const BuiltinArguments& args);即启动对应的service,对应vold.rc文件如下。

service vold /system/bin/vold \        --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \        --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0    class core    ioprio be 2    writepid /dev/cpuset/foreground/tasks    shutdown critical    group root reserved_disk

接下来看一下vold的main函数(由于篇幅原因,只列出来部分主要过程),简要概括为以下几个过程:

  1. 初始化Log函数;
  2. 解析rc中的参数,创建vold块设备节点;
  3. 获取NM和VM单例对象;
  4. 启动NM、VoldNativeService和VM;
  5. 创建线程池,并进入循环,维持进程不退出;
int main(int argc, char** argv) {    android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); //初始化Log类    VolumeManager* vm;    NetlinkManager* nm;    parse_args(argc, argv);//解析参数    mkdir("/dev/block/vold", 0755);//创建vold节点,用来接收uevent消息;    if (!(vm = VolumeManager::Instance())) {        LOG(ERROR) << "Unable to create VolumeManager";        exit(1);    }    if (!(nm = NetlinkManager::Instance())) {        LOG(ERROR) << "Unable to create NetlinkManager";        exit(1);    }    if (vm->start()) {   //启动vm        PLOG(ERROR) << "Unable to start VolumeManager";        exit(1);    }    android::hardware::configureRpcThreadpool(1, false /* callerWillJoin */);    ATRACE_BEGIN("VoldNativeService::start");    if (android::vold::VoldNativeService::start() != android::OK) {  //启动aidl接口        LOG(ERROR) << "Unable to start VoldNativeService";        exit(1);    }   if (nm->start()) { //启动nm        PLOG(ERROR) << "Unable to start NetlinkManager";        exit(1);    }    android::IPCThreadState::self()->joinThreadPool();  //进入循环    LOG(INFO) << "vold shutting down";    exit(0);}

接下来着重看一下3个start函数分别都做了什么。首先看一下VM:

int VolumeManager::start() {    ATRACE_NAME("VolumeManager::start");    // Always start from a clean slate by unmounting everything in    // directories that we own, in case we crashed.    unmountAll();    Devmapper::destroyAll();    Loop::destroyAll();    // Assume that we always have an emulated volume on internal    // storage; the framework will decide if it should be mounted.    CHECK(mInternalEmulated == nullptr);    mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(        new android::vold::EmulatedVolume("/data/media"));    mInternalEmulated->create();    // Consider creating a virtual disk    updateVirtualDisk();    return 0;}

从给到的注释来看,VM会先卸载掉对应文件夹中的所有东西,使之处于一个干净的状态,接着会构造出内置存储目录,也即/data/media,此处通过VolumeBase基类指针new了一个EmulatedVolume对象。在create函数中,执行了doCreate以及回调了onVolumeCreated,此处的listener则是SM服务,但是由于Vold启动较早,SystemServer还没有启动SM,所以这里getListener()得到的是空,后面SM启动完成后会重新触发。最后便是设置了当前存储设备的状态为unmounted。其中doCreate是虚函数,但是EmulatedVolume中并没有实现,所以最终还是调用了基类函数,也就直接返回了。最后根据给的注释可知,Vold会创建一个虚拟磁盘,即/data/misc/vold/virtual_disk。

status_t VolumeBase::create() {    CHECK(!mCreated);    mCreated = true;    status_t res = doCreate();    auto listener = getListener();    if (listener) {        listener->onVolumeCreated(getId(), static_cast<int32_t>(mType), mDiskId, mPartGuid);    }    setState(State::kUnmounted);    return res;}status_t VolumeBase::doCreate() {    return OK;}

到这里,VM的启动过程基本上就结束了,至于/data/media的挂载过程放到后面的章节去阐述。接着按照顺序来看一下aidl接口的启动,连接着SM和vold。

status_t VoldNativeService::start() {    IPCThreadState::self()->disableBackgroundScheduling(true);    status_t ret = BinderService<VoldNativeService>::publish();    if (ret != android::OK) {        return ret;    }    sp<ProcessState> ps(ProcessState::self());    ps->startThreadPool();    ps->giveThreadPoolName();    return android::OK;}

启动的过程相对比较简单,VoldNativeService继承自BinderService,start主要注册了接口,使其他服务可以通过IVold可以找到,然后启动线程。
 
最后就是NM了,同样来看一下start函数,内部建立了一个socket连接,用于接收所有的uevent事件,最后会new一个NetlinkHandler对象,并执行start函数,然后会调用NetlinkListener父类的startListener函数去监听event。

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 | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)) < 0) {        PLOG(ERROR) << "Unable to create uevent socket";        return -1;    }    // When running in a net/user namespace, SO_RCVBUFFORCE will fail because    // it will check for the CAP_NET_ADMIN capability in the root namespace.    // Try using SO_RCVBUF if that fails.    if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) &&        (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) {        PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option";        goto out;    }    if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {        PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option";        goto out;    }    if (bind(mSock, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {        PLOG(ERROR) << "Unable to bind uevent socket";        goto out;    }    mHandler = new NetlinkHandler(mSock);    if (mHandler->start()) {        PLOG(ERROR) << "Unable to start NetlinkHandler";        goto out;    }    return 0;out:    close(mSock);    return -1;}

到这里Vold的启动过程基本就结束了,后续Vold会监听kernel的uevent事件,然后处理转发通过Callback通知到SM,而Framework的服务以及App则可以通过SM去使用Vold处理Command。本篇着重讲了Vold进程的启动,下一篇着重看下各层级之间的联系是如何建立的。

更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)OpenGL ES
  3. Android与ok6410板子tcp通信
  4. Android之——杀死用户选中的进程优化
  5. [置顶] AIDL使用以及原理分析
  6. Android(安卓)OkHttp的Cookie自动化管理
  7. Android(安卓)IPC机制(二)——利用Messenger实现跨进程通信
  8. Android判断手机中的应用是否具有某些权限(例如小米手机中是否具
  9. android activity 生命周期详解

随机推荐

  1. Android(安卓)Studio : Rendering Proble
  2. Android: Your JS Engine is not always
  3. android 欢迎界面
  4. Android(安卓)实现图片轮播的三种方法
  5. android中获取SHA1的代码
  6. android休眠运行
  7. 开机不锁屏
  8. Android(安卓)日常报错之 Android(安卓)d
  9. Android动态加载及hook资料汇总
  10. Android圆环形自定义进度条控件的绘制