本文选取go库cgofuse举例,cgofuse是golang 对fuse以及windows 底层文件系统的封装,跨windows 、linux、ios

很多开源的 云平台对象存储 挂载客户端 也是基于此库

把元数据放在内里面就是基于内存的文件系统

把元数据放在数据库里面,则可以打造一个对象存储 & 文件系统的系统

文件系统挂载对象

type FileSystemHost struct {
// contains filtered or unexported fields
}

func (host *FileSystemHost) Mount(mountpoint string, opts []string) bool

新建一个挂载对象, FileSystemInterface 是一个抽象的文件系统的接口

func NewFileSystemHost(fsop FileSystemInterface) *FileSystemHost

看一下FileSystemInterface都包含哪些方法,实现一个用户态文件系统,具体就是实现这些方法

type FileSystemInterface interface {
// Init is called when the file system is created.
Init()

// Destroy is called when the file system is destroyed.
Destroy()

// Statfs gets file system statistics.
Statfs(path string, stat *Statfs_t) int

// Mknod creates a file node.
Mknod(path string, mode uint32, dev uint64) int

// Mkdir creates a directory.
Mkdir(path string, mode uint32) int

// Unlink removes a file.
Unlink(path string) int

// Rmdir removes a directory.
Rmdir(path string) int

// Link creates a hard link to a file.
Link(oldpath string, newpath string) int

// Symlink creates a symbolic link.
Symlink(target string, newpath string) int

// Readlink reads the target of a symbolic link.
Readlink(path string) (int, string)

// Rename renames a file.
Rename(oldpath string, newpath string) int

// Chmod changes the permission bits of a file.
Chmod(path string, mode uint32) int

// Chown changes the owner and group of a file.
Chown(path string, uid uint32, gid uint32) int

// Utimens changes the access and modification times of a file.
Utimens(path string, tmsp []Timespec) int

// Access checks file access permissions.
Access(path string, mask uint32) int

// Create creates and opens a file.
// The flags are a combination of the fuse.O_* constants.
Create(path string, flags int, mode uint32) (int, uint64)

// Open opens a file.
// The flags are a combination of the fuse.O_* constants.
Open(path string, flags int) (int, uint64)

// Getattr gets file attributes.
Getattr(path string, stat *Stat_t, fh uint64) int

// Truncate changes the size of a file.
Truncate(path string, size int64, fh uint64) int

// Read reads data from a file.
Read(path string, buff []byte, ofst int64, fh uint64) int

// Write writes data to a file.
Write(path string, buff []byte, ofst int64, fh uint64) int

// Flush flushes cached file data.
Flush(path string, fh uint64) int

// Release closes an open file.
Release(path string, fh uint64) int

// Fsync synchronizes file contents.
Fsync(path string, datasync bool, fh uint64) int

// Opendir opens a directory.
Opendir(path string) (int, uint64)

// Readdir reads a directory.
Readdir(path string,
fill func(name string, stat *Stat_t, ofst int64) bool,
ofst int64,
fh uint64) int

// Releasedir closes an open directory.
Releasedir(path string, fh uint64) int

// Fsyncdir synchronizes directory contents.
Fsyncdir(path string, datasync bool, fh uint64) int

// Setxattr sets extended attributes.
Setxattr(path string, name string, value []byte, flags int) int

// Getxattr gets extended attributes.
Getxattr(path string, name string) (int, []byte)

// Removexattr removes extended attributes.
Removexattr(path string, name string) int

// Listxattr lists extended attributes.
Listxattr(path string, fill func(name string) bool) int
}

文件的 数据结构

type Stat_t struct {
// Device ID of device containing file. [IGNORED]
Dev uint64

// File serial number. [IGNORED unless the use_ino mount option is given.]
Ino uint64

// Mode of file.
Mode uint32

// Number of hard links to the file.
Nlink uint32

// User ID of file.
Uid uint32

// Group ID of file.
Gid uint32

// Device ID (if file is character or block special).
Rdev uint64

// For regular files, the file size in bytes.
// For symbolic links, the length in bytes of the
// pathname contained in the symbolic link.
Size int64

// Last data access timestamp.
Atim Timespec

// Last data modification timestamp.
Mtim Timespec

// Last file status change timestamp.
Ctim Timespec

// A file system-specific preferred I/O block size for this object.
Blksize int64

// Number of blocks allocated for this object.
Blocks int64

// File creation (birth) timestamp. [OSX and Windows only]
Birthtim Timespec

// BSD flags (UF_*). [OSX and Windows only]
Flags uint32
}

说一下一些方法,或者说踩过的坑

Getattr

// Getattr gets file attributes
Getattr(path string, stat *Stat_t, fh uint64) int

此方法是调用最多的方法
因为对一个文件(文件夹)增删改查、修改属性、权限等等操作都会先获取文件属性
以判断条件是否可以进行下一步操作
windows 是没有像linux一样的权限系统的(uid ,gid)
如果按照linux下面的mode 或者随便给一个 你会发现在windows下没有权限

所以在windows下可以直接获取 然后给一个固定的值即可
uid, gid, _ := fuse.Getcontext()

Write

Write(path string, buff []byte, ofst int64, fh uint64) int

写文件方法,每次固定写入4K,注意这里是写入内存

Flush

Flush(path string, fh uint64) int
将文件写入磁盘
如果是对象存储则是写入远程存储,如果是采用http协议,
要注意nginx等中间件client_body_size等限制,分次发送

Fsync

Fsync(path string, datasync bool, fh uint64) int
在写入内存过程中,触发保存磁盘操作

Truncate

写入行为
命令行下 重定向输入 ">" 会触发truncate 追加输入">>" 则不会触发
Truncate(path string, size int64, fh uint64) (n int)
删除文件
Unlink(path string) int

Utimens

Utimens(path string, tmsp []fuse.Timespec) 
修改文件时间,重要,因为文件是靠mtime 来判断文件是否一致

Chmod

修改文件权限
Chmod(path string, mode uint32) int

Rename

重命名文件
Rename(oldpath string, newpath string)