当前位置:首页>Linux>Linux下使用fuse编写文件系统(2)

Linux下使用fuse编写文件系统(2)

  • 2026-09-02 20:31:50
Linux下使用fuse编写文件系统(2)
在《Linux下使用fuse编写文件系统(1)》一文中,我们知道如何在Linux系统环境下使用fuse编写一个简单的文件系统oufs,并且支持ls命令操作,接下来,我们完善补充增加创建和删除普通文件操作的功能,相应代码如下:
#define FUSE_USE_VERSION 26#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<fuse.h>#include"list.h"#define MAX_NAMELEN 255struct ou_entry {    mode_t mode;    struct list_node node;    char name[MAX_NAMELEN + 1];};static struct list_node entries;staticintou_readdir(constchar* path, void* buf, fuse_fill_dir_t filler,                      off_t offset, struct fuse_file_info* fi){    struct list_node* n;    filler(buf, ".", NULL, 0);    filler(buf, "..", NULL, 0);    list_for_each (n, &entries) {        struct ou_entry* o = list_entry(n, struct ou_entry, node);        filler(buf, o->name, NULL, 0);    }    return 0;}staticintou_getattr(constchar* path, struct stat* st){    struct list_node* n;    memset(st, 0, sizeof(struct stat));    if (strcmp(path, "/") == 0) {        st->st_mode = 0755 | S_IFDIR;        st->st_nlink = 2;        st->st_size = 0;        list_for_each (n, &entries) {            struct ou_entry* o = list_entry(n, struct ou_entry, node);            ++st->st_nlink;            st->st_size += strlen(o->name);        }        return 0;    }    list_for_each (n, &entries) {        struct ou_entry* o = list_entry(n, struct ou_entry, node);        if (strcmp(path + 1, o->name) == 0) {            st->st_mode = o->mode;            st->st_nlink = 1;            return 0;        }    }    return -ENOENT;}staticintou_create(constchar* path, mode_t mode, struct fuse_file_info* fi){    struct ou_entry* o;    struct list_node* n;    if (strlen(path + 1) > MAX_NAMELEN)        return -ENAMETOOLONG;    list_for_each (n, &entries) {        o = list_entry(n, struct ou_entry, node);        if (strcmp(path + 1, o->name) == 0)            return -EEXIST;    }    o = malloc(sizeof(struct ou_entry));    strcpy(o->name, path + 1); /* skip leading '/' */    o->mode = mode | S_IFREG;    list_add_prev(&o->node, &entries);    return 0;}staticintou_unlink(constchar* path){    struct list_node *n, *p;    list_for_each_safe (n, p, &entries) {        struct ou_entry* o = list_entry(n, struct ou_entry, node);        if (strcmp(path + 1, o->name) == 0) {            __list_del(n);            free(o);            return 0;        }    }    return -ENOENT;}static struct fuse_operations oufs_ops = {    .getattr    =   ou_getattr,    .readdir    =   ou_readdir,    .create     =   ou_create,    .unlink     =   ou_unlink,};intmain(int argc, char* argv[]){    list_init(&entries);    return fuse_main(argc, argv, &oufs_ops, NULL);}
代码中使用到的链表操作list.h文件内容如下:
#ifndef __LIST_H__#define __LIST_H__/* doubly linked list implementation from linux kernel */#define offset_of(type, member) \    ((unsigned long)(&(((type*)0)->member)))#define container_of(ptr, type, member) \    ((type*)((unsigned long)(ptr) - offset_of(type, member)))#define list_entry(ptr, type, member) container_of(ptr, type, member)struct list_node {    struct list_node *prev, *next;};staticinlinevoidlist_init(struct list_node* list){    list->prev = list;    list->next = list;}staticinlinevoidlist_add_prev(struct list_node* node,                                 struct list_node* next){    node->next = next;    node->prev = next->prev;    next->prev = node;    node->prev->next = node;}static inline void __list_del(struct list_node* node){    node->prev->next = node->next;    node->next->prev = node->prev;}staticinlinevoidlist_del(struct list_node* node){    __list_del(node);    list_init(node);}#define list_for_each(p, head) \    for ((p) = (head)->next; (p) != (head); (p) = (p)->next)#define list_for_each_safe(p, n, head) \    for ((p) = (head)->next, (n) = (p)->next; \         (p) != (head); \         (p) = (n), (n) = (p)->next)#endif
可以看到,我们的代码中新增了两个函数ou_create()和ou_unlink(),分别用于创建和删除文件;增加了一个全局变量entries用于保存所有的entry;ou_readdir() 和 ou_getattr() 也做了相应的修改。由于这些函数相当于实现VFS中的接口,因此不能在错误时返回-1了事,而是要根据不同的错误类型返回不同的值。关于错误代码头文件为errno.h,值和含义在 /usr/include/asm-generic/errno-base.h和/usr/include/asm-generic/errno.h有定义。

编译挂载后试试执行“touch /tmp/mnt/abc”,然后ls看看是否多了一个文件abc?

最新文章

随机文章