您好,登錄后才能下訂單哦!
今天小編給大家分享一下linux fuse功能怎么實現的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
在Linux中,fuse是指用戶態文件系統,是用于支持用戶空間文件系統的內核模塊;fuse是一個實現在用戶空間的文件系統框架,通過FUSE內核模塊的支持,使用者只需要根據fuse提供的接口實現具體的文件操作就可以實現一個文件系統。
linux fuse是什么
Linux用于支持用戶空間文件系統的內核模塊名叫FUSE,FUSE一詞有時特指Linux下的用戶空間文件系統。
是一個通用操作系統重要的組成部分。傳統上操作系統在內核層面上對文件系統提供支持。而通常內核態的代碼難以調試,生產率較低。
Linux從2.6.14版本開始通過FUSE模塊支持在用戶空間實現文件系統。
在用戶空間實現文件系統能夠大幅提高生產率,簡化了為操作系統提供新的文件系統的工作量,特別適用于各種虛擬文件系統和網絡文件系統。上述ZFS和glusterfs都屬于網絡文件系統。但是,在用戶態實現文件系統必然會引入額外的內核態/用戶態切換帶來的開銷,對性能會產生一定影響。
fuse主要作用:監控某個文件或者文件夾的變化,可以對其他進程在此文件夾或者文件中寫入或者讀取的東西增加自定義信息。
總結:
FUSE (用戶態文件系統)是一個實現在用戶空間的文件系統框架,通過 FUSE內核模塊的支持,使用者只需要根據 fuse 提供的接口實現具體的文件操作就可以實現一個文件系統。
FUSE 由三個部分組成,FUSE 內核模塊,FUSE 庫以及一些掛在工具。FUSE 內核模塊實現了和 VFS 的對接,它看起來像一個普通的文件系統模塊,另外 FUSE 內核模塊實現了一個可以被用戶空間進程打開的設備,當 VFS 發來文件操作請求之后,它將該請求轉化為特定格式,并通過設備傳遞給用戶空間進程,用戶空間進程在處理完請求后,將結果返回給 FUSE 內核模塊,內核模塊再將其還原為Linux Kernel 需要的格式,并返回給 VFS。
FUSE 庫負責和內核空間的通信,它接收來自/dev/fuse 的請求,并將其轉化為一系列的函數調用,并將結果寫回到/dev/fuse。
struct fuse_operations {
int (*getattr) (const char *, struct stat *, struct fuse_file_info *fi);
int (*readlink) (const char *, char *, size_t);
int (*mknod) (const char *, mode_t, dev_t);
int (*mkdir) (const char *, mode_t);
int (*unlink) (const char *);
int (*rmdir) (const char *);
int (*symlink) (const char *, const char *);
int (*rename) (const char *, const char *, unsigned int);
int (*link) (const char *, const char *);
int (*chmod) (const char *, mode_t, struct fuse_file_info *fi);
int (*chown) (const char *, uid_t, gid_t, struct fuse_file_info *fi);
int (*truncate) (const char *, off_t, struct fuse_file_info *fi);
int (*open) (const char *, struct fuse_file_info *);
int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
int (*statfs) (const char *, struct statvfs *);
int (*flush) (const char *, struct fuse_file_info *);
int (*release) (const char *, struct fuse_file_info *);
int (*fsync) (const char *, int, struct fuse_file_info *);
int (*setxattr) (const char *, const char *, const char *, size_t, int);
int (*getxattr) (const char *, const char *, char *, size_t);
int (*listxattr) (const char *, char *, size_t);
int (*removexattr) (const char *, const char *);
int (*opendir) (const char *, struct fuse_file_info *);
int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t,
struct fuse_file_info *, enum fuse_readdir_flags);
int (*releasedir) (const char *, struct fuse_file_info *);
int (*fsyncdir) (const char *, int, struct fuse_file_info *);
void (init) (struct fuse_conn_info *conn,struct fuse_config *cfg);
void (*destroy) (void *);
int (*access) (const char *, int);
int (*create) (const char *, mode_t, struct fuse_file_info *);
int (*lock) (const char *, struct fuse_file_info *, int cmd,struct flock *);
int (*utimens) (const char *, const struct timespec tv[2], struct fuse_file_info *fi);
int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
int (*ioctl) (const char *, int cmd, void *arg,
struct fuse_file_info *, unsigned int flags, void *data);
int (*poll) (const char *, struct fuse_file_info *,
struct fuse_pollhandle *ph, unsigned *reventsp);
int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off,struct fuse_file_info *);
int (*read_buf) (const char *, struct fuse_bufvec **bufp,
size_t size, off_t off, struct fuse_file_info *);
int (*flock) (const char *, struct fuse_file_info *, int op);
int (*fallocate) (const char *, int, off_t, off_t,struct fuse_file_info *);
};
1.安裝:
(1)./configure --prefix=/usr
(2)make
(3)make install
2.加載驅動
加載fuse.ko模塊“modprobe fuse”,然后在切換到example目錄下編譯fusexmp.c
內核源碼在:內核源碼/fs/fuse
1.fuse內核模塊被加載時,以下初始化例程會被調用,見fuse_init函數<inode.c>。
(1)fuse_fs_init(); 注冊fuse文件系統,創建fuse_inode高速緩存。
(2)fuse_dev_init(); 創建fuse_req高速緩存,加載fuse設備驅動,用于用戶空間與內核空間交換信息。
(3)fuse_sysfs_init(); 在/sys/fs目錄下增加fuse節點,在fuse節點下增加connections節點。
(4)fuse_ctl_init(); 注冊fuse控制文件系統
2.fuse內核模塊被卸載時,執行對應的清理工作,見fuse_exit函數<inode.c>
(1)fuse_ctl_cleanup(); 注銷fuse控制文件系統
(2)fuse_sysfs_cleanup(); 移除fuse、connections節點。
(3)fuse_fs_cleanup(); 注銷fuse文件系統,釋放fuse_inode高速緩存。
(4)fuse_dev_cleanup(); 注銷fuse設備驅動程序,釋放fuse_req高速緩存。
3. fuse_conn<fuse_i.h>代表一個fuse連接,當用戶文件系統被掛載時生成該結構,當文件系統被卸載時釋放該結構,其主要用于管理各個請求隊列,內核會為所有掛載的文件系統維護一個fuse_conn的鏈表(fuse文件系統可能會被掛載多次)。
4.fuse_conn的connected字段用于表示連接的狀態,成功掛載后為1,當文件系統被卸載,連接被中斷或是設備驅動被釋放后,該字段為0,此時這個connection(掛載的文件系統)不能提供正常服務。在fuse_request_send中會檢查該字段,只有連接正常fuse文件系統才會發送請求。
5.fuse中每個請求用一個fuse_req<fuse_i.h>的結構表示,該結構中包含fuse請求的輸入輸出參數,請求對象的inode、file等。
6.每個fuse的輸入、輸出參數都支持三個參數,見fuse_in、fuse_out結構的定義<fuse_i.h>,參數以<*value, size>的形式傳遞,當填充fuse_req結構時,根據請求類型,以及請求參數,設置fuse_in的參數個數(numargs),并將參數填充到args數組中,同時設置fuse_out輸出參數的個數,并將存放輸出結果的地址(局部變量outarg)填充到args數組中。
7.當fuse文件系統設置好請求輸入輸出參數之后,所有接口最后都會調用fuse_request_send將代表本次請求的fuse_req結構的狀態標志設置為FUSE_REQ_PENDING,將請求加到fuse_conn的pending鏈表中,并調用request_wait_answer等待請求完成(等待隊列被喚醒后,需要檢查請求狀態是否為FUSE_REQ_FINISHED)。當本次請求被響應后,結果已經被存放在局部變量outarg中,fuse進行相應的處理即可向上層返回結果。
8.每個請求fuse_req結構中包含一個wait_queue_head_t的waitq字段,每個請求在被發出之后,它首先會喚醒fuse_conn的waitq等待隊列,告訴用戶態守護進程有請求達到;然后其會調用wait_event_interruptible在req的waitq上睡眠等待FUSE_REQ_FINISHED條件變為真。
9.fuse設備驅動是一個簡單塊設備驅動程序,用于fuse在用戶態和內核態之間交換數據,fuse包含一個用戶空間的守護程序,其一直循環運行,主要任務是調用read從fuse設備上讀取請求,當沒有請求時,它會在fuse_conn的waitq上睡眠等待(對應上一段中請求發出后喚醒fuse_conn的waitq等待隊列),當有請求是其從fuse_conn的pengding隊列中取出最前的一個請求(對應上一段中請求發出后加到fuse_conn的pending鏈表),并將該請求移動到processing隊列中,守護進程將fuse_req的相關信息讀到用戶態后,根據請求表示調用用戶態實現的回調函數,并將結果通過fuse_dev_write寫到fuse設備驅動,用戶態請求完成后,從processing隊列中找到對應的fuse_req,將結果拷貝到fuse_req的out參數中,并將fuse_req的state設置為FUSE_REQ_FINISHED,然后喚醒fuse_req的waitq。此時,fuse_req被處理完畢,fuse文件系統向上層返回。
以上就是“linux fuse功能怎么實現”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。