In Linux, fuse refers to the user-space file system, which is a kernel module used to support user-space file systems; fuse is a file system framework implemented in user-space. With the support of the FUSE kernel module, use The author only needs to implement specific file operations according to the interface provided by fuse to implement a file system.
#The operating environment of this tutorial: linux7.3 system, Dell G3 computer.
What is linux fuse
The kernel module used by Linux to support user space file systems is called FUSE , the term FUSE sometimes refers specifically to the user space file system under Linux.
is an important part of a general operating system. Operating systems have traditionally provided support for file systems at the kernel level. Generally, kernel-mode code is difficult to debug and has low productivity.
Linux supports the implementation of file systems in user space through the FUSE module starting from version 2.6.14.
Implementing file systems in user space can greatly improve productivity and simplify the workload of providing new file systems for the operating system. It is especially suitable for various virtual file systems and network file systems. The above-mentioned ZFS and glusterfs are both network file systems. However, implementing a file system in user mode will inevitably introduce additional overhead caused by kernel mode/user mode switching, which will have a certain impact on performance.
The main function of fuse: Monitor changes in a file or folder, and add custom information to what other processes write or read in this folder or file.
Summary:
FUSE (user mode file system) is a file system framework implemented in user space. With the support of the FUSE kernel module, users only need to The interface provided by fuse implements specific file operations to implement a file system.
FUSE consists of three parts, the FUSE kernel module, the FUSE library and some hanging tools. The FUSE kernel module implements docking with VFS. It looks like an ordinary file system module. In addition, the FUSE kernel module implements a device that can be opened by a user space process. When VFS sends a file operation request, it will Convert it into a specific format and pass it to the user space process through the device. After processing the request, the user space process returns the result to the FUSE kernel module. The kernel module then restores it to the format required by the Linux Kernel and returns it to VFS.
## The FUSE library is responsible for communicating with the kernel space. It receives requests from /dev/fuse, converts them into a series of function calls, and writes the results back to /dev/fuse.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函数
(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函数
(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
4. The connected field of fuse_conn is used to indicate the status of the connection. It is 1 after successful mounting. When the file system is unmounted, the connection is interrupted or the device driver is released, the field is 0. At this time This connection (mounted file system) cannot provide normal services. This field will be checked in fuse_request_send, and the request will be sent only when the normal fuse file system is connected.
5. Fuse_req & lt; fuse_i.h & gt; in each request in Fuse_req & LT; fuse_i.h.h & gt;
6. The input and output parameters of each fuse support three parameters. See the definition of fuse_in and fuse_out structures
7. After the fuse file system sets the request input and output parameters, all interfaces will finally call fuse_request_send to set the status flag of the fuse_req structure representing this request to FUSE_REQ_PENDING, and add the request to the pending linked list of fuse_conn , and call request_wait_answer to wait for the request to be completed (after the waiting queue is awakened, you need to check whether the request status is FUSE_REQ_FINISHED). When this request is responded to, the result has been stored in the local variable outarg, and fuse performs corresponding processing to return the result to the upper layer.
8. Each request fuse_req structure contains a waitq field of wait_queue_head_t. After each request is issued, it will first wake up the waitq waiting queue of fuse_conn and tell the user mode daemon that a request has arrived; then other Wait_event_interruptible will be called to sleep on the waitq of req and wait for the FUSE_REQ_FINISHED condition to become true.
9. The fuse device driver is a simple block device driver, used by fuse to exchange data between user mode and kernel mode. fuse contains a user space daemon, which runs in a loop. Its main task is Call read to read the request from the fuse device. When there is no request, it will sleep and wait on the waitq of fuse_conn (corresponding to waking up the waitq waiting queue of fuse_conn after the request is issued in the previous paragraph). When there is a request, it will wait from the pengding queue of fuse_conn. Take out the first request (corresponding to the pending linked list added to fuse_conn after the request in the previous paragraph), and move the request to the processing queue. After the daemon reads the relevant information of fuse_req into the user state, it calls the user according to the request. State-implemented callback function, and write the result to the fuse device driver through fuse_dev_write. After the user-state request is completed, find the corresponding fuse_req from the processing queue, copy the result to the out parameter of fuse_req, and set the state of fuse_req to FUSE_REQ_FINISHED , and then wake up the waitq of fuse_req. At this point, fuse_req is processed and the fuse file system returns to the upper layer.
Related recommendations: "Linux Video Tutorial"
The above is the detailed content of what is linux fuse. For more information, please follow other related articles on the PHP Chinese website!