共計 3914 個字符,預計需要花費 10 分鐘才能閱讀完成。
本篇內容主要講解“linux fuse 指的是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“linux fuse 指的是什么”吧!
Linux 用于支持用戶空間文件系統的內核模塊名叫 FUSE。fuse 全稱“Filesystem in Userspace”,中文意思為“用戶空間文件系統”,指完全在用戶態實現的文件系統,是 Linux 中用于掛載某些網絡空間,是一個通用操作系統重要的組成部分。
linux fuse 是什么
用戶空間文件系統(Filesystem in Userspace),指完全在用戶態實現的文件系統,是 Linux 中用于掛載某些網絡空間,如 SSH,到本地文件系統的模塊,在 SourceForge 上可以找到相關內容。
Linux 用于支持用戶空間文件系統的內核模塊名叫 FUSE,FUSE 一詞有時特指 Linux 下的用戶空間文件系統。是一個通用操作系統重要的組成部分。傳統上操作系統在內核層面上對文件系統提供支持。而通常內核態的代碼難以調試,生產率較低。
所謂“用戶態文件系統”,是指一個文件系統的 data 和 metadata 都是由用戶態的進程提供的(這種進程被稱為 daemon)。對于 micro-kernel 的操作系統來說,在用戶態實現文件系統不算什么,但對于 macro-kernel 的 Linux 來說,意義就有所不同。
雖然叫做用戶態文件系統,但不代表其完全不需要內核的參與,因為在 Linux 中,對文件的訪問都是統一通過 VFS 層提供的內核接口進行的(比如 open/read),因此當一個進程(稱為 user)訪問由 daemon 實現的文件系統時,依然需要途徑 VFS。
當 VFS 接到 user 進程對文件的訪問請求,并且判斷出該文件是屬于某個用戶態文件系統(根據 mount type),就會將這個請求轉交給一個名為 fuse 的內核模塊。而后,fuse 將該請求轉換為和 daemon 之間約定的協議格式,傳送給 daemon 進程。
可見,在這個三方關系中,fuse 這個內核模塊起的是一個轉接的作用,它幫助建立了 VFS(也可以說是 user 進程)和 daemon 之間的交流通道,通俗點說,它的角色其實就是一個「代理」。
這一整套框架的實現在 Linux 中即為 FUSE (Filesystem in Userspace)。如圖 1 所示,紅框的部分才是 FUSE 類型文件系統的具體實現,才是用戶態文件系統的設計者可以發揮的空間。目前,已有不下百種基于 FUSE 實現的文件系統(一些基于內核的文件系統也可以 porting 成用戶態文件系統,比如 ZFS 和 NTFS),而本文將選用一個現成的 fuse-sshfs 來進行演示。
首先安裝 fuse-sshfs 的軟件包,使用如下的命令進行文件系統的 mount(將遠端機器的 remote-dir 目錄掛載到本機的 local-dir 目錄):
sshfs remote-ip : remote-dir local-dir
之后,在 /sys/fs 目錄下,將生成一個名為 fuse 的文件夾,同時可以看到 fuse 內核模塊已被加載(其對應的設備為 /dev/fuse),并且本機的掛載目錄的類型已成為 fuse.sshfs:
生成設備節點的目的是方便用戶態的控制,但是對于文件系統這種級別的應用來說,直接使用 ioctl() 來訪問設備還是顯得麻煩,因為呈現了太多的細節,所以 libfuse 作為一個中間層應運而生,daemon 進程實際都是通過 libfuse 提供的接口來操作 fuse 設備文件的。
你來我往
接下來,以在 fuse.sshfs 文件系統中通過 touch 命令新建一個文件為例,查看 fuse 內核模塊和 daemon 進程(即 sshfs)具體的交互流程(代碼部分基于內核 5.2.0 版本):
【第一輪】
最開始是 permission 的校驗,不過這里的校驗并不等同于 VFS 的權限校驗,它的主要目的是為了避免其他 user 訪問到了自己私有的 fuse 文件系統。
然后就是根據文件路徑查找文件的 inode。由于是新建的文件,inode 并不在內核的 inode cache 中,所以需要向 daemon 發送 lookup 的請求:
這些請求會被放入一個 pending queue 中,等待 daemon 進程的回復,而 user 進程將陷入睡眠:
作為 daemon,sshfs 進程通過讀取 /dev/fuse 設備文件來獲得數據,如果 pending queue 為空,它將陷入阻塞等待:
當 pending queue 上有請求到來時,daemon 進程將被喚醒并處理這些請求。被處理的請求會被移入 processing queue,待 daemon 進程向 fuse 內核模塊做出 reply 之后,user 進程將被喚醒,對應的 request 將從 processing queue 移除。
【第二輪】
接下來就是執行 touch 命令時所觸發的其他系統調用,如果是之前訪問過的 data/metadata,那很可能存在于 cache 中,再次訪問這部分 data/metadata 的時候,fuse 內核模塊就可以自行解決,不需要去用戶空間往返一趟,否則還是需要上報 daemon 進程進行處理。
這里 get_fuse_conn() 獲取的是在 fuse 類型的文件系統被 mount 時創建的 fuse_conn 結構體實例。作為 daemon 進程和 kernel 聯系的紐帶,除非 daemon 進程消亡,或者對應的 fuse 文件系統被卸載,否則該 connection 將一直存在。
在 daemon 進程這一端,還是類似的操作。需要注意的是區別 fuse_write/read() 和 fuse_dev_write/read() 這兩個系列的函數,前者是 user 進程在訪問 fuse 文件系統上的文件時的 VFS 讀寫請求,屬于對常規文件的操作,而后者是 daemon 進程對 /dev/fuse 這個代表 fuse 內核模塊的設備的讀寫,目的是為了獲取 request 和給出 reply。
【第三輪】
fuse 內核模塊和 daemon 進程的最后一輪交互是在代表 fuse 文件系統的 superblock 中獲取 inode 號,并填寫這個 metadata 的相關信息。
硬幣的兩面
不難發現,在 fuse 文件系統中,即便執行一個相對簡單的 touch 操作,所涉及的用戶態和內核態的切換都是比較頻繁的,并且還伴隨著多次的數據拷貝。相比于傳統的內核文件系統,它整體的 I / O 吞吐量更低,而延遲也更大。
那為什么 fuse 在操作系統支持的文件系統里面依然占據一席之地呢?說起來,在用戶態開發是有很多優勢的。一是便于調試,特別適合做一個新型文件系統 prototype 的快速驗證,因此在學術研究領域頗受青睞。在內核里面,你只能用 C 語言吧,到了用戶態,就沒那么多限制了,各種函數庫,各種編程語言,都可以上。
二是內核的 bug 往往一言不合就導致整個系統 crash(在虛擬化的應用中更為嚴重,因為宿主機的 crash 會導致其上面運行的所有虛擬機 crash),而用戶態的 bug 所造成的影響相對有限一些。
所以,硬幣的正面是便于開發,不過到底有多方便,這畢竟是一種主觀的感受,而反面則是性能的影響,這可是能夠用客觀的實驗數據來驗證的。那應該用什么方法才能相對準確地衡量 fuse 所帶來的損耗呢?
還是用前面用過的這個 fuse-sshfs,不過這里我們不再使用遠端掛載,而是采用本地掛載的方式(假設本機的 dir-src 目錄位于 ext4 文件系統):
sshfs localhost: dir-src dir-dst
當 daemon 進程收到請求后,它需要再次進入內核,去訪問 ext4 的內核模塊(這種文件系統模式被稱為 stackable 的):
以 user 進程向 fuse 文件系統發出 write() 請求為例,右邊紅框部分是一次原生的 ext4 調用路徑,而左邊多出來的就是因為引入 fuse 后增加的路徑:
根據這篇文檔給出的數據,在這一系統調用中使用到的 getxattr 所形成的 request,需要 2 倍的 user-kernel 交互量。對于順序寫,相比起原生的 ext4 文件系統,I/ O 吞吐量降低 27%,隨機寫則降低 44%。
不過,在 fuse 文件系統誕生的這么多年里,大家還是為它想出了很多的優化舉措。比如,順序讀寫的時候,可以設計為向 daemon 進程批量發送 request 的形式(但隨機讀寫不適合)。
還有就是使用 splicing 這種 zero-copy 技術,由 Linux 內核提供的 splicing 機制允許用戶空間在轉移兩個內核的內存 buffer 的數據時,不需要拷貝,因此尤其適合 stackable 模式下,從 fuse 內核模塊直接向 ext4 內核模塊傳遞數據(但 splicing 通常用于超過 4K 的請求,小數據量的讀寫用不上)。
經過這些努力,fuse 文件系統的性能可以達到什么樣的一種程度呢?根據這篇報告列出的測試結果,相比起原生的 ext4,在最理想的情況下,fuse 的性能損耗可以控制到 5% 以內,但最差的情況則是 83%。同時,其對 CPU 的資源占用也增加了 31%。
從 Android v4.4 到 v7.0 之間存在的 sdcard daemon,到最近幾年的 Ceph 和 GlusterFS,都曾經采用過或正在采用基于 FUSE 的實現。FUSE 在 network filesystem 和虛擬化應用中都展現了自己的用武之地,它的出現和發展,并不是要取代在內核態實現的文件系統,而是作為一個有益的補充(理論上,FUSE 還可以用于實現根文件系統,但是不建議這么做,can do 和 should do 是兩回事)。
到此,相信大家對“linux fuse 指的是什么”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!