自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android內(nèi)卡掛載之FUSE文件系統(tǒng)

原創(chuàng)
開(kāi)發(fā) 前端
FUSE(Filesystem in Userspace),是一種用戶空間文件系統(tǒng)。用戶可以通過(guò)FUSE文件系統(tǒng)操作內(nèi)卡。FUSE主要實(shí)現(xiàn)代碼位于用戶空間中,而不需要重新編譯到內(nèi)核,用戶空間開(kāi)發(fā)者可以通過(guò)FUSE的接口直接訪問(wèn)內(nèi)核空間,不需要了解文件系統(tǒng)的內(nèi)幕和內(nèi)核模塊編程的知識(shí),這給用戶空間開(kāi)發(fā)者帶來(lái)了眾多便利。

作者 | 陳豪

審校 | 孫淑娟

一、簡(jiǎn)介

FUSE(Filesystem in Userspace),是一種用戶空間文件系統(tǒng)。用戶可以通過(guò)FUSE文件系統(tǒng)操作內(nèi)卡。FUSE主要實(shí)現(xiàn)代碼位于用戶空間中,而不需要重新編譯到內(nèi)核,用戶空間開(kāi)發(fā)者可以通過(guò)FUSE的接口直接訪問(wèn)內(nèi)核空間,不需要了解文件系統(tǒng)的內(nèi)幕和內(nèi)核模塊編程的知識(shí),這給用戶空間開(kāi)發(fā)者帶來(lái)了眾多便利。

二、FUSE文件系統(tǒng)架構(gòu)

1.FUSE內(nèi)核模塊(內(nèi)核態(tài))實(shí)現(xiàn)VFS 接口(FUSE文件驅(qū)動(dòng)注冊(cè)、supper block、dentry、inode的維護(hù)),接收請(qǐng)求傳遞給LibFUSE,LibFUSE 再傳遞給用戶程序的接口進(jìn)行操作。

2.LibFUSE模塊(用戶態(tài))實(shí)現(xiàn)文件系統(tǒng)主要框架,比如對(duì)實(shí)現(xiàn)的文件系統(tǒng)操作進(jìn)行封裝、mount管理、通過(guò)設(shè)備/dev/fuse與內(nèi)核模塊通信。

3.用戶程序模塊(用戶態(tài))當(dāng)內(nèi)卡掛載成功后,對(duì)內(nèi)卡進(jìn)行讀寫操作。

這種架構(gòu)的設(shè)計(jì)可以讓用戶通過(guò)FUSE在用戶空間來(lái)定制自己的文件系統(tǒng),將文件系統(tǒng)從內(nèi)核剝離出來(lái),大大縮減了開(kāi)發(fā)的難度。本文將著重介紹libfuse如何掛載內(nèi)卡。

三、內(nèi)卡的掛載

3.1 內(nèi)卡掛載與分區(qū)掛載的不同

分區(qū)掛載是掛載到內(nèi)核實(shí)地文件系統(tǒng),例如userdata分區(qū)掛載f2fs到 /data目錄下。內(nèi)卡掛載是掛載用戶空間文件系統(tǒng),如dev/fuse 掛載fuse到mnt/user/0/emulated目錄下。

上圖mnt/user/0/emulated和/data/media/0下的內(nèi)容是一樣的。原因是這兩個(gè)目錄是綁定的關(guān)系,說(shuō)明內(nèi)卡是userdata的一部分。這部分空間是用戶可以直接操作的。

在手機(jī)的文件管理器中也可以看到同樣的目錄:

3.2 內(nèi)卡掛載和綁定

VoldNativeService::mount接收到framwork層發(fā)送的mount請(qǐng)求后調(diào)用vol->mount,從而執(zhí)行VolumeBase::mount這個(gè)父類。真正的實(shí)現(xiàn)是在子類內(nèi)卡會(huì)調(diào)用EmulatedVolume::doMount執(zhí)行掛載。

1.VoldNativeService::mount

mountFlags決定掛載的是內(nèi)卡還是SD卡,為3時(shí)掛載內(nèi)卡,為2時(shí)掛載SD卡。內(nèi)卡的mountUserId為0,SD卡的mountUserId是卡本身的guid。最終會(huì)執(zhí)行vol->mount()。

binder::Status VoldNativeService::mount(
  const std::string& volId, int32_t mountFlags, int32_t mountUserId,
  const android::sp<android::os::IVoldMountCallback>& callback) {
  ENFORCE_SYSTEM_OR_ROOT;
  CHECK_ARGUMENT_ID(volId);
  ACQUIRE_LOCK;
 
  auto vol = VolumeManager::Instance()->findVolume(volId);
  if (vol == nullptr) {
  return error("Failed to find volume " + volId);
  }
 
  vol->setMountFlags(mountFlags);
  vol->setMountUserId(mountUserId);
 
  vol->setMountCallback(callback);
  int res = vol->mount();
  vol->setMountCallback(nullptr);
 
  if (res != OK) {
  return translate(res);
  }
 
  return translate(OK);
 }

2.vol->mount

vol是VolumeBase的實(shí)例,VolumeBase的mount方法由具體的子類EmulatedVolume、PublicVolume、PrivateVolume等實(shí)現(xiàn)。執(zhí)行操作之后會(huì)發(fā)送應(yīng)答消息給MountService。將掛載的結(jié)果上報(bào)給framwork層。

status_t VolumeBase::mount() {
  if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
  LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
  return -EBUSY;
  }
  setState(State::kChecking);
  status_t res = doMount();
  setState(res == OK ? State::kMounted : State::kUnmountable);
 
  if (res == OK) {
  doPostMount();
  }
  return res;
 }

3.EmulatedVolume::doMount ()

內(nèi)卡會(huì)走到EmulatedVolume這個(gè)子類進(jìn)行掛載,SD卡則會(huì)走PublicVolume掛載。在EmulatedVolume函數(shù)里建立了四個(gè)/mnt/runtime路徑并設(shè)置了不同的權(quán)限,原因是控制不同權(quán)限APP訪問(wèn)。然后利用掛載命名空間實(shí)現(xiàn)了掛載點(diǎn)的隔離,用戶在不同掛載命名空間的進(jìn)程,看到的目錄層次不同。MountUserFuse是掛載FUSE的實(shí)現(xiàn),內(nèi)卡和SD卡都會(huì)走這個(gè)流程。著重看一下MountUserFuse函數(shù)的實(shí)參,如果掛載的是內(nèi)卡,user_id則為0,getInternalPath()為/data/media,label為emulated。

status_t EmulatedVolume::doMount() {
  std::string label = getLabel();
  bool isVisible = getMountFlags() & MountFlags::kVisible;
  mSdcardFsDefault = StringPrintf("/mnt/runtime/default/%s", label.c_str());
  mSdcardFsRead = StringPrintf("/mnt/runtime/read/%s", label.c_str());
  mSdcardFsWrite = StringPrintf("/mnt/runtime/write/%s", label.c_str());
  mSdcardFsFull = StringPrintf("/mnt/runtime/full/%s", label.c_str());
 
  setInternalPath(mRawPath);
  setPath(StringPrintf("/storage/%s", label.c_str()));

………………………………
res = MountUserFuse(user_id, getInternalPath(), label, &fd);

…………………………..
}

4.MountUserFuse();

如下函數(shù)中只粘貼了重要的部分。fuse_path是掛載路徑mnt/user/0/emulated。隨后調(diào)用mount函數(shù)調(diào)用內(nèi)核接口進(jìn)行掛載,將/dev/fuse 掛載到/mnt/user/0/emulated。

status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
  const std::string& relative_upper_path, android::base::unique_fd* fuse_fd) {

std::string fuse_path(
  StringPrintf("%s/%s", pre_fuse_path.c_str(), relative_upper_path.c_str()));

result = TEMP_FAILURE_RETRY(mount("/dev/fuse", fuse_path.c_str(), "fuse",
  MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME | MS_LAZYTIME,
  opts.c_str()));
}

掛載成功后可以用mount命令去查看,截圖如下:

四、總結(jié)

本文介紹了內(nèi)卡對(duì)FUSE的掛載,將創(chuàng)建好的FUSE設(shè)備掛載到內(nèi)置存儲(chǔ)空間關(guān)聯(lián)目錄。對(duì)于內(nèi)置存儲(chǔ)空間的訪問(wèn)變成了先訪問(wèn)FUSE文件系統(tǒng),再訪問(wèn)f2fs文件系統(tǒng)。對(duì)于FUSE而言,在內(nèi)核空間和用戶空間來(lái)回切換會(huì)增加性能開(kāi)銷,所以對(duì)FUSE的性能優(yōu)化至關(guān)重要。

作者介紹

陳豪,51CTO社區(qū)編輯,具有6年工作經(jīng)驗(yàn)的高級(jí)系統(tǒng)工程師。擅長(zhǎng)技能有Linux內(nèi)嵌匯編語(yǔ)言,Python,C,C++,Java,Linux內(nèi)核分析,智能機(jī)器人軟件設(shè)計(jì)等。

參考鏈接

??https://blog.csdn.net/kongxinsun/article/details/79587305??

??https://blog.csdn.net/bob_fly1984/article/details/80720807??


責(zé)任編輯:華軒 來(lái)源: 51CTO
相關(guān)推薦

2014-02-26 11:41:33

Fuse文件系統(tǒng)

2018-06-08 15:56:52

LinuxBittorrent文件系統(tǒng)

2023-09-27 23:19:04

Linuxmount

2014-01-24 09:58:45

fuse文件系統(tǒng)

2021-05-31 07:50:59

Linux文件系統(tǒng)

2018-05-29 09:00:00

LinuxBTFS文件系統(tǒng)

2010-01-08 18:01:03

Ubuntu硬盤操作

2021-08-25 10:10:52

findmnt命令Linux

2021-03-10 08:02:58

Findmnt命令系統(tǒng)

2010-03-02 15:09:26

Linux mount

2010-01-26 13:41:50

Android文件系統(tǒng)

2009-10-28 14:29:40

linux文件系統(tǒng)

2017-04-25 15:50:02

sparse傳輸處理

2020-07-22 14:53:06

Linux系統(tǒng)虛擬文件

2018-11-05 09:45:01

Linux文件系統(tǒng)命令

2010-01-26 15:08:11

Android根文件系

2020-01-03 08:33:57

Ceph硬件系統(tǒng)

2023-04-12 15:09:25

Overlay fs鴻蒙

2011-01-13 14:10:30

Linux文件系統(tǒng)

2018-08-24 10:10:25

Linux文件系統(tǒng)技術(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)