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]), atoi(argv[3