1. 程式人生 > >Android8.0 儲存系統

Android8.0 儲存系統

Android 一直在不斷髮展,可支援各種儲存裝置型別和功能。所有 Android 版本均支援配有傳統儲存(包括行動式儲存和內建儲存)的裝置。行動式儲存是指物理介質(如 SD 卡或 USB 裝置),用於進行臨時資料傳輸/檔案儲存。物理介質可以隨裝置一起保留更長時間,但並非固定在裝置上,可以移除。自 Android 1.0 開始,SD 卡已可用作行動式儲存;Android 6.0 增加對 USB 的支援。“內建”儲存可通過將部分內部儲存暴露於模擬層來實現儲存,並且從 Android 3.0 開始便已支援此功能。

1. 後臺程序Vold啟動

system\vold\main.cpp

int
main(int argc, char** argv) { VolumeManager *vm; //卷管理 CommandListener *cl; //命令監聽 CryptCommandListener *ccl;//加密監聽 NetlinkManager *nm;//連線管理 parse_args(argc, argv); sehandle = selinux_android_file_context_handle(); //selinux if (sehandle) { selinux_android_set_sehandle(sehandle);
} // Quickly throw a CLOEXEC on the socket we just inherited from init fcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC); //建立Vold通道 fcntl(android_get_control_socket("cryptd"), F_SETFD, FD_CLOEXEC); //建立加密通道 mkdir("/dev/block/vold", 0755); //建立檔案 if (!(vm = VolumeManager::Instance
())) { exit(1);} if (!(nm = NetlinkManager::Instance())) { exit(1);} cl = new CommandListener(); //建立註冊一系列監聽命令 ccl = new CryptCommandListener(); // vm->setBroadcaster((SocketListener *) cl); nm->setBroadcaster((SocketListener *) cl); if (vm->start()) { exit(1); } if (process_config(vm, &has_adoptable)) {} if (nm->start()) { exit(1);} if (cl->startListener()) { exit(1);} if (ccl->startListener()) {exit(1);} property_set("vold.has_adoptable", has_adoptable ? "1" : "0"); coldboot("/sys/block"); while(1) { pause(); } exit(0); }

2. CommandListener 與 VolumeManager

system\vold\CommandListener.cpp
註冊一系列命令,這些Cmd均繼承自VoldCommand,VoldCommand繼承自FrameworkCommand

CommandListener::CommandListener() :
                 FrameworkListener("vold", true) {
    registerCmd(new DumpCmd());
    registerCmd(new VolumeCmd());
    registerCmd(new AsecCmd());
    registerCmd(new ObbCmd());
    registerCmd(new StorageCmd()); //儲存命令
    registerCmd(new FstrimCmd());
    registerCmd(new AppFuseCmd());
}

system\core\libsysutils\src\FrameworkListener.cpp

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

system\core\libsysutils\src\SocketListener.cpp

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

system\core\libsysutils\src\SocketListener.cpp
mClient 是一個List定義在SocketClient.h

void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
    mListen = listen;
    mSocketName = socketName;
    mSock = socketFd;
    mUseCmdNum = useCmdNum;
    pthread_mutex_init(&mClientsLock, NULL);
    mClients = new SocketClientCollection();
}

system\vold\CryptCommandListener.cpp
加密監聽也是一樣的

FrameworkListener("cryptd", true) {
    registerCmd(new CryptfsCmd());
}

system\vold\VolumeManager.h
system\vold\NetlinkManager.h

  void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }

system\vold\VolumeManager.cpp

int VolumeManager::start() {
    //清除狀態防止崩潰
    unmountAll();
    //確保掛在內部儲存
    CHECK(mInternalEmulated == nullptr);
    mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
            new android::vold::EmulatedVolume("/data/media"));
    mInternalEmulated->create();
    //建立一個虛擬盤
    updateVirtualDisk();

    return 0;
}

system\core\libsysutils\src\SocketListener.cpp
啟動加密,和命令監聽

int SocketListener::startListener() {
    return startListener(4);
}

system\core\libsysutils\src\SocketListener.cpp

int SocketListener::startListener(int backlog) {

    if (!mSocketName && mSock == -1) {
        errno = EINVAL;
        return -1;
    } else if (mSocketName) {
        if ((mSock = android_get_control_socket(mSocketName)) < 0) { //mSock由系統控制提供
            return -1;
        }
        fcntl(mSock, F_SETFD, FD_CLOEXEC); //建立Socket, mSock檔案描述符
    }

    if (mListen && listen(mSock, backlog) < 0) {
        return -1;
    } else if (!mListen){
       mClients->push_back(new SocketClient(mSock, false, mUseCmdNum)); //入佇列
    }
    if (pipe(mCtrlPipe)) { return -1; }
    //建立執行緒,指定處理函式 threadStart
    if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {return -1;}

    return 0;
}

system\core\libsysutils\src\SocketListener.cpp

void *SocketListener::threadStart(void *obj) {
    SocketListener *me = reinterpret_cast<SocketListener *>(obj); 
    me->runListener();
    pthread_exit(NULL);
    return NULL;
}

system\core\libsysutils\src\SocketListener.cpp
開始迴圈監聽

void SocketListener::runListener() {

    SocketClientCollection pendingList;

    while(1) {
        SocketClientCollection::iterator it;
        fd_set read_fds;
        int rc = 0;
        int max = -1;

        FD_ZERO(&read_fds);

        if (mListen) {
            max = mSock;
            FD_SET(mSock, &read_fds);
        }

        FD_SET(mCtrlPipe[0], &read_fds);
        if (mCtrlPipe[0] > max)
            max = mCtrlPipe[0];

        pthread_mutex_lock(&mClientsLock); //加鎖
        for (it = mClients->begin(); it != mClients->end(); ++it) {
            // NB: calling out to an other object with mClientsLock held (safe)
            int fd = (*it)->getSocket(); //獲取檔案描述符
            FD_SET(fd, &read_fds);
            if (fd > max) {
                max = fd;
            }
        }
        pthread_mutex_unlock(&mClientsLock);
        //使用Socket的select
        if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
            if (errno == EINTR)
                continue;
            SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);
            sleep(1);
            continue;
        } else if (!rc)
            continue;

         ......

        /* Process the pending list, since it is owned by the thread,
         * there is no need to lock it */
        while (!pendingList.empty()) {
            /* Pop the first item from the list */
            it = pendingList.begin();
            SocketClient* c = *it;
            pendingList.erase(it);
            /* Process it, if false is returned, remove from list */
            if (!onDataAvailable(c)) { //開始處理
                release(c, false);
            }
            c->decRef();
        }
    }
}

system\core\libsysutils\src\FrameworkListener.cpp
由子類實現的onDataAvailable函式處理

bool FrameworkListener::onDataAvailable(SocketClient *c) {
    char buffer[CMD_BUF_SIZE]; //命令緩衝陣列
    int len;

    len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); //讀取
    
    if (len < 0) {
        return false;
    } else if (!len) {
        return false;
    } else if (buffer[len-1] != '\0') { //讀取到末尾
        android_errorWriteLog(0x534e4554, "29831647");
        c->sendMsg(500, "Command too large for buffer", false); 
        mSkipToNextNullByte = true;
        return false;
    }

    int offset = 0;
    int i;

    for (i = 0; i < len; i++) {
        if (buffer[i] == '\0') {
            /* IMPORTANT: dispatchCommand() expects a zero-terminated string */
            if (mSkipToNextNullByte) {
                mSkipToNextNullByte = false;
            } else {
                dispatchCommand(c, buffer + offset);
            }
            offset = i + 1;
        }
    }

    mSkipToNextNullByte = false;
    return true;
}

system\core\libsysutils\src\FrameworkListener.cpp
由FrameworkCommand的子孫類去執行命令

void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
    .....
    FrameworkCommandCollection::iterator i;
    for (i = mCommands->begin(); i != mCommands->end(); ++i) {
        FrameworkCommand *c = *i;

        if (!strcmp(argv[0], c->getCommand())) {
            if (c->runCommand(cli, argc, argv)) { //執行命令
                SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
            }
            goto out;
        }
    }
   ......
}

system\vold\CommandListener.cpp
處理來自上層系統的命令,掛載,監聽

CommandListener::VolumeCmd::VolumeCmd() :
                 VoldCommand("volume") {
}

int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
                                           int argc, char **argv) {
    VolumeManager *vm = VolumeManager::Instance();
    std::lock_guard<std::mutex> lock(vm->getLock());

    // TODO: tease out methods not directly related to volumes

    std::string cmd(argv[1]);
    if (cmd == "reset") {
        return sendGenericOkFail(cli, vm->reset());

    } else if (cmd == "shutdown") {
        return sendGenericOkFail(cli, vm->shutdown());

    } else if (cmd == "debug") {
        return sendGenericOkFail(cli, vm->setDebug(true));

    } else if (cmd == "partition" && argc > 3) {
        // partition [diskId] [public|private|mixed] [ratio]
        std::string id(argv[2]);
        auto disk = vm->findDisk(id);
        if (disk == nullptr) {
            return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown disk", false);
        }

        std::string type(argv[3]);
        if (type == "public") {
            return sendGenericOkFail(cli, disk->partitionPublic());
        } else if (type == "private") {
            return sendGenericOkFail(cli, disk->partitionPrivate());
        } else if (type == "mixed") {
            if (argc < 4) {
                return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false);
            }
            int frac = atoi(argv[4]);
            return sendGenericOkFail(cli, disk->partitionMixed(frac));
        } else {
            return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false);
        }

    } else if (cmd == "mkdirs" && argc > 2) {
        // mkdirs [path]
        return sendGenericOkFail(cli, vm->mkdirs(argv[2]));

    } else if (cmd == "user_added" && argc > 3) {
        // user_added [user] [serial]
        return sendGenericOkFail(cli, vm->onUserAdded(atoi(argv[2]), at