日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

FUSE简介

發布時間:2024/6/21 综合教程 36 生活家
生活随笔 收集整理的這篇文章主要介紹了 FUSE简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是FUSE

傳統的文件系統是操作系統的一部分,放在操作系統內核里面實現。Fuse(Filesystem in Userspace), 一個用戶空間文件系統框架,提供給我們一組用于實現一個文件系統的API,使我們可以在用戶態實現自已的文件系統。

FUSE的優缺點

1)傳統文件系統都是定義在操作系統內核層面上的,要操作系統識別一種新的文件系統,必需重寫內核,而內核態代碼難以調試,生產率較低;但是用戶空間編程和調試難度較小,有更多的語言可以選擇(目前FUSE已經綁定了很多語言,比如c++、java等),還可以復用已有的庫),從而能夠大幅提高生產率,極大地簡少了為操作系統提供新的文件系統的工作量。

2)一些服務可以通過統一的文件系統接口來進行訪問,比如說ftp、sftp、samba

3)可以把非文件的服務當做文件來實現,比如把gmail提供的巨大的空間用來進行文件存儲的Gmail Filesystem

4)在用戶態實現文件系統必然會引入額外的內核態/用戶態切換帶來的開銷,對性能會產生一定影響。

FUSE的結構

fuse包括三個模塊:用戶空間庫,內核模塊以及mount工具

1)用戶空間庫給程序員提供編程接口,程序員通過實現fuse提供的兩組接口fuse_lowlevel_ops,fuse_operations之一即可實現一個用戶空間文件系統

2)內核模塊實現了一個完整文件系統的框架,但具體操作沒有實現(由程序員在用戶空間實現)

3)mount工具fusermount用于掛載基于fuse的文件系統

定義FUSE需要的函數

fuse為開發者提供了兩組接口,分別是fuse_lowlevel_ops以及fuse_operations,開發者只需要實現這兩組接口的一種即可實現一個用戶空間文件系統。

struct fuse_lowlevel_ops的成員如下所示,其中init方法在其它所有方法之前調用,用于初始化文件系統,fuse已經實現,destroy則是在文件系統被卸載時做一些清理工作。用于大多數請求的參數都是fuse_ino_t類型的ino,而文件系統提供給用戶的視圖是以文件名呈現的,故lookup是實現文件系統的關鍵,它在parent中查找名字name對應的文件,并返回相應的信息,可使用fuse_reply_entry或fuse_reply_err作為請求的返回。

接口中的方法對于了解過VFS的人應該都不難理解,只要按需實現這些接口,你就可以定制出屬于自己的文件系統,這組接口的詳細說明見fuse_lowlevel.h。

void(* init )(void *userdata, struct fuse_conn_info *conn)
void(* destroy )(void *userdata)
void(* lookup )(fuse_req_t req, fuse_ino_t parent, const char *name)
void(* forget )(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup)
void(* getattr )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(* setattr )(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi)
void(* readlink )(fuse_req_t req, fuse_ino_t ino)
void(* mknod )(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev)
void(* mkdir )(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
void(* unlink )(fuse_req_t req, fuse_ino_t parent, const char *name)
void(* rmdir )(fuse_req_t req, fuse_ino_t parent, const char *name)
void(* symlink )(fuse_req_t req, const char *link, fuse_ino_t parent, const char *name)
void(* rename )(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname)
void(* link )(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname)
void(* open )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(* read )(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
void(* write )(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, structfuse_file_info *fi)
void(* flush )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(* release )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(* fsync )(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
void(* opendir )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(* readdir )(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
void(* releasedir )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void(* fsyncdir )(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
void(* statfs )(fuse_req_t req, fuse_ino_t ino)
void(* setxattr )(fuse_req_t req, fuse_ino_t ino, const char *name, const char *value, size_t size, int flags)
void(* getxattr )(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
void(* listxattr )(fuse_req_t req, fuse_ino_t ino, size_t size)
void(* removexattr )(fuse_req_t req, fuse_ino_t ino, const char *name)
void(* access )(fuse_req_t req, fuse_ino_t ino, int mask)
void(* create )(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, struct fuse_file_info*fi)
void(* getlk )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock)
void(* setlk )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock, int sleep)
void(* bmap )(fuse_req_t req, fuse_ino_t ino, size_t blocksize, uint64_t idx)
void(* ioctl )(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, struct fuse_file_info *fi, unsigned *flagsp, const void *in_buf, size_t in_bufsz, size_t out_bufszp)
void(* poll )(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct fuse_pollhandle *ph)

用戶實現的接口是如何跟這個結構關聯起來的?

其實fuse中已經實現了一組接口,在fuse_lowlevel.c中,定義了一個靜態的結構數組,該數組的元素為一組(函數,名字)的結構,但沒做什么實際的工作,當fuse用戶空間的daemon從/fuse/dev中讀取到請求之后,它通過請求號來判別各個請求,并調用這里相應的處理函數,如讀取到read調用時,會調用do_read進行處理。

static struct {
    void (*func)(fuse_req_t, fuse_ino_t, const void *);
    const char *name;
} fuse_ll_ops[] = {
    //只列舉了部分
    [FUSE_LOOKUP]      = { do_lookup,      "LOOKUP"      },
    [FUSE_OPEN]        = { do_open,        "OPEN"        },
    [FUSE_READ]        = { do_read,        "READ"        },
    [FUSE_WRITE]       = { do_write,       "WRITE"       },
    [FUSE_STATFS]      = { do_statfs,      "STATFS"      },
    [FUSE_FLUSH]       = { do_flush,       "FLUSH"       },
    [FUSE_INIT]        = { do_init,        "INIT"        },
    [FUSE_OPENDIR]     = { do_opendir,     "OPENDIR"     },
    [FUSE_READDIR]     = { do_readdir,     "READDIR"     },
    [FUSE_RELEASEDIR]  = { do_releasedir,  "RELEASEDIR"  },
    [FUSE_DESTROY]     = { do_destroy,     "DESTROY"     }
};

接下來看一下do_read的實現

static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
    struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
    // 如果用戶實現了read操作,則調用用戶空間的read,否則以沒有實現該調用為錯誤響應,這里的op就是用戶實現文件系統時實現的,并傳遞給fuse。
    if (req->f->op.read) {
        struct fuse_file_info fi;
        memset(&fi, 0, sizeof(fi));
        fi.fh = arg->fh;
        fi.fh_old = fi.fh;
        req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
    } else
        fuse_reply_err(req, ENOSYS);
}

從這里的實現可以看出,這些操作是沒有加任何鎖的,如果開發者需要文件系統鎖,需要在實現文件系統時自行考慮。

fuse_operations又是怎么一回事?

對于實現fuse_lowlevel_ops這組接口,沒有內核VFS相關知識的開發者是不可能完成的,為了增強fuse的通用性,使更多的用戶能夠使用fuse開發文件系統,fuse提供了一組更簡單的接口fuse_operations,詳細說明請參考fuse.h。這組接口的參數跟unix提供的系統調用的參數很類似,開發者更易理解,fuse想開發者屏蔽了底層的相關對象,直接以文件名作為參數,只有開發者按照自己的方式,把這組接口實現就可以,顯然這比上面那組接口的實現要簡單得多。

struct fuse_operations {
    int (*getattr) (const char *, struct stat *);
    int (*readlink) (const char *, char *, size_t);
    int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_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 *);
    int (*link) (const char *, const char *);
    int (*chmod) (const char *, mode_t);
    int (*chown) (const char *, uid_t, gid_t);
    int (*truncate) (const char *, off_t);
    int (*utime) (const char *, struct utimbuf *);
    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 statfs *);
    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 *);
};

這些操作并非都是必需的,但是一個文件系統要想正常工作,就需要其中的很多函數。

提供這組接口,fuse做了什么?

fuse還是實現了一組fuse_lowlevel_ops的接口,在fuse.c中

static struct fuse_lowlevel_ops fuse_path_ops = {
    //只列舉了部分方法
    .init = fuse_lib_init,
    .destroy = fuse_lib_destroy,
    .lookup = fuse_lib_lookup,
    .forget = fuse_lib_forget,
    .getattr = fuse_lib_getattr,
    .setattr = fuse_lib_setattr,
.access = fuse_lib_access,
.read = fuse_lib_read,
    .readlink = fuse_lib_readlink
};

fuse實現的這組接口跟之前的方法不一樣,不是什么都不做,它完成了部分工作,主要是文件節點與文件名的轉換關系,然后將文件名作為參數,調用用戶實現的fuse_operations的接口。

如fuse_lib_read的實現

int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
                 off_t off, struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
//用戶實現的方法
    if (fs->op.read)
        return fs->op.read(path, buf, size, off, fi);
    else
        return -ENOSYS;
}
 
static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
                          off_t off, struct fuse_file_info *fi)
{
    struct fuse *f = req_fuse_prepare(req);
    char *path;
    char *buf;
    int res;
 
    buf = (char *) malloc(size);
    if (buf == NULL) {
        reply_err(req, -ENOMEM);
        return;
    }
 
    res = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock); //fuse_operations使用了讀寫鎖
//由ino獲取path
    path = get_path(f, ino);
    if (path != NULL) {
        struct fuse_intr_data d;
        if (f->conf.debug)
            fprintf(stderr, "READ[%llu] %lu bytes from %llun",
                    (unsigned long long) fi->fh, (unsigned long) size,
                    (unsigned long long) off);
 
        fuse_prepare_interrupt(f, req, &d);
        res = fuse_fs_read(f->fs, path, buf, size, off, fi); //通過這個方法調用用戶實現的方法
        fuse_finish_interrupt(f, req, &d);
        free(path);
    }
    pthread_rwlock_unlock(&f->tree_lock);
 
    if (res >= 0) {
        if (f->conf.debug)
            fprintf(stderr, "   READ[%llu] %u bytesn",
                    (unsigned long long)fi->fh, res);
        if ((size_t) res > size)
            fprintf(stderr, "fuse: read too many bytes");
        fuse_reply_buf(req, buf, res); //返回結果
    } else
        reply_err(req, res);
 
    free(buf);

FUSE 流程

通過這幅圖可以看到三個模塊在fuse工作時所起的作用

fuse_main() (lib/helper.c)——fuse用戶空間主函數,用戶程序調用它時,fuse_main()函數解析相關參數(如mountpoint,multithreaded),并調用fuse_mount()函數,接著調用fuse_new()函數,為fuse文件系統數據分配存儲空間。最后調用fuse_loop()函數實現會話的接受與處理。

fuse_mount() (lib/mount.c)——創建UNIX本地套接口,創建并運行子進程fusermount。

fusermount (util/fusermount.c)——確保fuse模塊已經加載,通過UNIX套接口返回fuse模塊的文件fd給fuse_mount()函數。

fuse_new() (lib/fuse.c)——為fuse創建數據結構空間,用來存儲文件系統數據。

fuse_loop() (lib/fuse.c)( fuse_loop_mt() (lib/fuse_mt.c))——從/dev/fuse (/dev 設備文件存儲目錄)讀取文件系統調用,調用fuse_operations或fuse_lowlevel_ops結構中的處理函數,返回調用結果給/dev/fuse

FUSE Kernel模塊由兩部分組成:

第一部分——proc文件系統組件:Kernel/dev.c——回應io請求到/dev/fuse。fuse_dev_read()函數負責讀出文件,并將來自“list of request”結構體的命令返回到調用函數。fuse_dev_write ()負責文件寫入,并將寫入的數據置放到“req→out”數據結構中。

第二部分——文件系統調用部分:kernel/file.c,kernel/inode.c,kernel/dir.c——調用request_send(),將請求加入到“list of request”結構體中,等待回復(reply)。

Fuse調用流程

在shell里輸入命令,請求通過vfs到達fuse,然后通過用戶實現的fuse給出的API返回調用。

Fuse處理請求的核心工作就是進行隊列管理

兩個重要的數據結構 fc, req

/* A Fuse connection.
 * This structure is created, when the filesystem is mounted, and is destroyed, when the
 * client device is closed and the filesystem is unmounted. 
*/
Struct  fuse_conn
 {
/** Readers of the connection are waiting on this */
    wait_queue_head_t waitq; // 等待執行請求的進程的隊列
    /** The list of pending requests */
    struct list_head pending;  // 被掛起的請求 的隊列
    /** The list of requests being processed */
    struct list_head processing; // 正在被處理的請求的 隊列
/** Pending interrupts */
 struct list_head interrupts;  // 執行中被中斷的請求的 隊列
...
}
/*  
*A request to the client
 */
struct fuse_req
{
/** Used to wake up the task waiting for completion of request*/
    wait_queue_head_t waitq;  // 請求的等待隊列
…
}

fuse通過fuse_session_loop來啟動守護程序,守護程序最終會調用fuse_dev_readv, fuse_dev_readv調用request_wait,使得進程在fc的waitq隊列上睡眠。

Static  size_t  fuse_dev_readv(struct file *file, const struct iovec *iov,  unsigned long nr_segs, loff_t *off)                              
{
     ….
     request_wait(fc);
 ….
}
* Wait until a request is available on the pending list 
 *當前進程一直等待,直到掛起隊列中有一個請求
*/
static void request_wait(struct fuse_conn *fc)
{
DECLARE_WAITQUEUE(wait, current);  //定義一個隊列節點變量wait,其與當前進程相關聯
        add_wait_queue_exclusive(&fc->waitq, &wait);  //將wait加入到fc->waitq等待隊列中
        //不斷的檢查fc的pending隊列及interrupts隊列,看是否有請求,沒有請求一直while循環
         while (fc->connected && !request_pending(fc))
 {
             set_current_state(TASK_INTERRUPTIBLE);
             if (signal_pending(current)) break;
             spin_unlock(&fc->lock);
             schedule();  //選擇一個進程運行
             spin_lock(&fc->lock);
         } 
        // 有請求,將進程設為TASK_RUNNING狀態(被喚醒,被賦予CPU使用權)
        set_current_state(TASK_RUNNING); 
        remove_wait_queue(&fc->waitq, &wait); // 將wait(當前進程)從等待隊列中移除
}

③// fc的pending隊列及interrupts隊列,看是否有請求
static int request_pending(struct fuse_conn *fc)
{
return !list_empty(&fc->pending) || !list_empty(&fc->interrupts);
}

request_send是用戶請求經過vfs(如上面的圖),再到fuse operation中被調用的,它向/dev/fuse發送請求

void  request_send(struct fuse_conn *fc, struct fuse_req *req)
{
    ……
    queue_request(fc, req); 
 request_wait_answer(fc, req);
……
}

⑤static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
{
    list_add_tail(&req->list, &fc->pending);  //將請求加入到pending隊列
    req->state = FUSE_REQ_PENDING;
   if (!req->waiting)
 {
  req->waiting = 1;
  atomic_inc(&fc->num_waiting);
    }
wake_up(&fc->waitq);  //喚醒等待等列
    kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
/* Called with fc->lock held.  Releases, and then reacquires it. */
//該調用會在req的waitq上睡眠,fuse守護程序處理完請求后,會將其喚醒
static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
{
	     if (!fc->no_interrupt) 
{
		    /* Any signal may interrupt this */
		    wait_answer_interruptible(fc, req);
		   if (req->aborted)
			   goto aborted;
		   if (req->state == FUSE_REQ_FINISHED)
			   return; 
		   req->interrupted = 1;
		   if (req->state == FUSE_REQ_SENT)
			   queue_interrupt(fc, req);
	     }
	     if (req->force) {
		spin_unlock(&fc->lock);
		wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
		spin_lock(&fc->lock);
	     } else {
		   sigset_t oldset;
		/* Only fatal signals may interrupt this */
		block_sigs(&oldset);
		wait_answer_interruptible(fc, req);
		restore_sigs(&oldset);
	     }
	    if (req->aborted)
		    goto aborted;
	    if (req->state == FUSE_REQ_FINISHED)   return;
	req->out.h.error = -EINTR;
	req->aborted = 1;
aborted:
	if (req->locked) {
		/* This is uninterruptible sleep, because data is
		   being copied to/from the buffers of req.  During
		   locked state, there mustn't be any filesystem
		   operation (e.g. page fault), since that could lead
		   to deadlock */
		spin_unlock(&fc->lock);
		wait_event(req->waitq, !req->locked);
		spin_lock(&fc->lock);
	}
	if (req->state == FUSE_REQ_PENDING) {
		list_del(&req->list);
		__fuse_put_request(req);
	} else if (req->state == FUSE_REQ_SENT) {
		spin_unlock(&fc->lock);
		wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
		spin_lock(&fc->lock);
	}
}
}

 (左列七行)fuse守護程序處理完請求,最終通過fuse_dev_writev寫回/dev/fuse,它將喚醒相應req中waitq的等待隊列元素,從而讓文件系統請求完成request_wait_answer,獲取到結果。
⑦/**Write a single reply to a request.  First the header is copied from the write buffer.  The request is then *searched on the processing list by the unique ID found in the header.  If found, then remove it from the list *and copy the rest of the buffer to the request. The request is finished by calling request_end()
 */
static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,  unsigned long nr_segs, loff_t *off)                                                  
{
   ……..
req = request_find(fc, oh.unique);
   request_end(fc, req);
   ….
}
⑧/* * This function is called when a request is finished.  Either a reply has arrived or it was aborted (and not yet *sent) or some error occurred during communication with userspace, or the device file was closed.  The *requester thread is woken up (if still waiting), the 'end' callback is called if given, else the reference to the *request is released Called with fc->lock, unlocks it 
*/
static void request_end(struct fuse_conn *fc, struct fuse_req *req)
{
   ….
   wake_up(&req->waitq);  //喚醒req上的等待隊列
   ……
}

fuse通過fuse_session_loop(或對應多線程的方法)來啟動fuse守護程序,守護程序不斷的從/dev/fuse上讀取請求,并處理。

int fuse_session_loop(struct fuse_session *se) //在fuse_main中會被調用,或其多線程版本
{
    int res = 0;
    struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
    size_t bufsize = fuse_chan_bufsize(ch);
    char *buf = (char *) malloc(bufsize); //為channel分配好緩沖區
    if (!buf) {
        fprintf(stderr, "fuse: failed to allocate read buffer
");
        return -1;
}
//fuse daemon, loops
    while (!fuse_session_exited(se)) {
        struct fuse_chan *tmpch = ch;
// 從/dev/fuse讀請求,會等待一直到有請求為止
        res = fuse_chan_recv(&tmpch, buf, bufsize);
        if (res == -EINTR)   continue;
        if (res <= 0)       break;
        fuse_session_process(se, buf, res, tmpch);   //處理讀到的請求
    }
free(buf);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}
②int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
{
    struct fuse_chan *ch = *chp;
    if (ch->compat)
        return ((struct fuse_chan_ops_compat24 *) &ch->op)->receive(ch, buf, size);
    else
        return ch->op.receive(chp, buf, size); //由下面的一段代碼可以發現,receive最終是通過
// fuse_kern_chan_receive實現的,代碼片段3分析該請求
}
③#define MIN_BUFSIZE 0x21000
struct fuse_chan *fuse_kern_chan_new(int fd)
{
    //channel的讀寫方法
    struct fuse_chan_ops op = {
        .receive = fuse_kern_chan_receive,
        .send = fuse_kern_chan_send,
        .destroy = fuse_kern_chan_destroy,
};
//設置bufsize大小
    size_t bufsize = getpagesize() + 0x1000;
    bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
    return fuse_chan_new(&op, fd, bufsize, NULL);
}
static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,  size_t size)
{
    struct fuse_chan *ch = *chp;
    int err;
    ssize_t res;
    struct fuse_session *se = fuse_chan_session(ch);
    assert(se != NULL);
    // 一直輪詢,直到讀到請求為止
 restart:
    //fuse_chan_fd獲取到/dev/fuse的文件描述符,調用read系統調用從設備讀取請求
res = read(fuse_chan_fd(ch), buf, size); 
//根據fuse設備驅動程序file結構的實現(dev.c),read將調用fuse_dev_read,該方法最終通過fuse_dev_readv
//實現,根據代碼中的注釋,fuse_dev_read做了如下工作:
// Read a single request into the userspace filesystem's buffer.  This function waits until a request is available, 
// then removes it from the pending list and copies request data to userspace buffer.
// 而fuse_dev_read又調用request_wait,使得進程在fc->waitq上睡眠
    if no data: goto restart
    ………
}

以上的分析對應了fuse filesystem daemon做的第一部分工作。當用戶從控制臺輸入"rm /mnt/fuse/file"時,通過VFS(sys_unlink),再到fuse(dir.c中實現的inode_operations,file.c中實現的file_operations中的方法都會最終調用request_send,后面會講到),這個請求最終被發到了/dev/fuse中,該請求的到達會喚醒正在等待的fuse守護程序,fuse守護程序讀取該請求并進行處理,接下來介紹處理請求所作的工作。

⑤struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, 
                                      const struct fuse_lowlevel_ops *op,
                                       size_t op_size, void *userdata)
{
//fuse_lowlevel_ops在之前的文章
http://blog.chinaunix.net/u2/87570/showart_2166461.html中已經介紹//過了,開發者實現了fuse_lowlevel_ops并傳遞給fuse_lowlevel_common
    struct fuse_ll *f;
    struct fuse_session *se;
struct fuse_session_ops sop = {
    //最終調用的處理方法
        .process = fuse_ll_process, //分析見代碼片段5
        .destroy = fuse_ll_destroy,
    };
  …….
}
⑥static void fuse_ll_process(void *data, const char *buf, size_t len, struct fuse_chan *ch)
{
    struct fuse_ll *f = (struct fuse_ll *) data;
    struct fuse_in_header *in = (struct fuse_in_header *) buf;
    const void *inarg = buf + sizeof(struct fuse_in_header);
struct fuse_req *req;
    //創建并初始化一個請求
    req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
    if (req == NULL) {
        fprintf(stderr, "fuse: failed to allocate request
");
        return;
    }
    req->f = f;
req->unique = in->unique;
……
//根據opcode調用fuse_ll_ops中相應的方法,fuse_ll_ops的介紹
// http://blog.chinaunix.net/u2/87570/showart_2166461.html
    fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
    }
}

以上代碼對應中流程中perform unlink的工作,實際上就是執行開發者實現的一組方法來完成相關的工作,接下來就是把執行完請求后需要的數據返回,最終是通過send_reply實現的

⑦static int send_reply(fuse_req_t req, int error, const void *arg, size_t argsize)
{
    struct iovec iov[2];
    int count = 1;
    if (argsize) {
        iov[1].iov_base = (void *) arg;
        iov[1].iov_len = argsize;
        count++;
    }
    return send_reply_iov(req, error, iov, count);
}
⑧static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, int count)
{
    ……
    res = fuse_chan_send(req->ch, iov, count);
    free_req(req);
    return res;
}
⑨static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],  size_t count)
{
    if (iov) {
        //將數據寫到/dev/fuse上,最終會調用fuse_dev_write
        ssize_t res = writev(fuse_chan_fd(ch), iov, count);
    ……
    return 0;
}

另外fuse接收到VFS的請求時,通過request_send將請求發送到/fuse/dev,并調用request_wait_answer等待返回結果。至于fuse使用的隊列的管理,在流程圖中也做了簡單的說明,下一篇文章將詳細分析隊列的管理。

void request_send(struct fuse_conn *fc, struct fuse_req *req)
{
         req->isreply = 1;
         spin_lock(&fc->lock);
         if (!fc->connected)
                   req->out.h.error = -ENOTCONN;
         else if (fc->conn_error)
                   req->out.h.error = -ECONNREFUSED;
         else {
        //將請求加入請求隊列
                   queue_request(fc, req);
                   /* acquire extra reference, since request is still needed after request_end() */
                   __fuse_get_request(req);
        //等待結果
                   request_wait_answer(fc, req);
         }
         spin_unlock(&fc->lock);
}

  

總結

以上是生活随笔為你收集整理的FUSE简介的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 色老太hd老太色hd | 亚洲在线色 | 在线免费av网站 | 99有精品 | 亚洲第九十七页 | 久久好色 | 狠狠婷| 午夜一区不卡 | 国产乱xxⅹxx国语对白 | 婷婷九月| 少妇又紧又色 | 久久精品国产亚洲av麻豆色欲 | 最近2018年手机中文字幕版 | 91av福利 | 91久久精品无码一区二区 | 国产crm系统91在线 | 91欧美一区二区 | 成年人av网站 | 久久丫精品国产亚洲av不卡 | 91免费网站入口 | 久久成年视频 | 动漫av网站 | 精品在线观看一区二区 | 女生扒开尿口给男生捅 | 99ri在线观看| 福利国产视频 | 钰慧的mv视频在线观看 | 操人小视频 | 亚洲国产aⅴ精品一区二区 日韩黄色在线视频 | 免费在线观看视频 | 啪啪在线视频 | 爱情岛论坛亚洲自拍 | 亚洲日本一区二区 | 扒开jk护士狂揉免费 | 亚洲男人第一天堂 | 久久调教 | 天天综合天天添夜夜添狠狠添 | 国产噜噜噜噜噜久久久久久久久 | 丁香免费视频 | v天堂中文在线 | 性欧美欧美巨大69 | 日本少妇b | 久久免费电影 | 国产在线啪 | 天堂网在线资源 | 国产黄频 | 久久久精品网站 | 日韩www视频 | 国产一级二级视频 | 日韩视频一区在线观看 | 91女神在线 | 日本在线观看免费 | 欧美爽爽爽 | 天堂网在线最新版www中文网 | 青青草成人免费视频 | 国产高清视频一区 | 污色视频 | 国产精品久久久久9999爆乳 | 国产九色91回来了 | 亚洲欧美综合另类 | 男人天堂综合网 | 亚洲精品女人久久久 | 五级黄高潮片90分钟视频 | 国产二区电影 | 亚洲成人伊人 | 日韩视频国产 | 成人免费黄色网 | 精品国产乱码久久久人妻 | porn国产| 亚洲国产欧美日韩在线 | v在线 | 久久精品免费看 | 中国免费黄色片 | 一线毛片| 东京av男人的天堂 | 国产3页 | 日韩国产欧美综合 | 冈本视频在线观看 | 神马久久春色 | 伊人av一区 | 欧美极品少妇xxxxⅹ免费视频 | 丰满饥渴老女人hd | 精品国产视频在线 | 久久99热这里只有精品 | 97潮色| 在线观看免费高清视频 | 黄色网页入口 | 青青草久久伊人 | 泰国午夜理伦三级 | 伊人久久婷婷 | 在线观看国产一区二区三区 | 激情福利| 性做久久久久久久久 | 极品三级| 欧美激情三级 | 欧美日韩国产精品 | 美女视频久久 | 日韩欧美一区二区三区久久婷婷 | 中文字幕一区二区人妻视频 |