libfuse源码:GitHub - libfuse/libfuse: The reference implementation of the Linux FUSE (Filesystem in Userspace) interface
一、ubuntu20.04挂载fuse文件系统
1,安装编译工具
apt install ninja-build
apt install meson
apt install build-essential
apt install python3-pip
pip install pytest (编译fuse自测模块用到,可选,一般不需要)
2,下载libfuse代码
创建下载目录fuse:
root@linux:/home/gsf# mkdir fuse; cd fuse/
从github下载libfuse代码:
root@linux:/home/gsf/fuse# git clone https://github.com/libfuse/libfuse.git
Cloning into 'libfuse'...
remote: Enumerating objects: 12797, done.
remote: Counting objects: 100% (53/53), done.
remote: Compressing objects: 100% (32/32), done.
remote: Total 12797 (delta 26), reused 32 (delta 21), pack-reused 12744
Receiving objects: 100% (12797/12797), 3.57 MiB | 807.00 KiB/s, done.
Resolving deltas: 100% (9867/9867), done.
3,编译libfuse
在源码目录创建build目录,并进入build:
root@linux:/home/gsf/fuse# cd libfuse/; mkdir build; cd build/;
编译:
root@linux:/home/gsf/fuse/libfuse/build# meson ..
root@linux:/home/gsf/fuse/libfuse/build# python3 -m pytest test/ (可选,fuse自测模块,一般不需要)
root@linux:/home/gsf/fuse/libfuse/build# ninja install
4,编译fuse文件系统
将自己写的一个fuse文件系统源码放在fuse源码/libfuse/build目录中,比如从fuse源码/libfuse/example目录中拷贝hello.c(自带的一个简单fuse文件系统)只build目录,单独编译(必须要先编译libfuse,因为会用到其中的库),然后挂载:
root@linux:/home/gsf/fuse/libfuse/build# cp ../example/hello.c .
root@linux:/home/gsf/fuse/libfuse/build# gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello
root@linux:/home/gsf/fuse/libfuse/build# ./hello /mnt/fusemnt/
root@linux:/home/gsf/fuse/libfuse/build#
5,挂载fuse
编译libfuse时,已经编译了libfuse source code中exampl目录自带的fuse文件系统,这些编译好的文件在libfuse/build/example/目录,比如我们用编译出来的hello执行挂载命令(这个hello就是一个简单的fuse文件系统):
创建挂载点:
root@linux:/home/gsf/fuse/libfuse/build/example# mkdir -p /mnt/fusemnt
挂载fuse文件系统:
root@linux:/home/gsf/fuse/libfuse/build/example# ./hello /mnt/fusemnt
mount命令检查fuse是否挂载成功:
root@linux:/home/gsf/fuse/libfuse/build/example# mount |grep fuse
fusectl on /sys/fs/fuse/connections type fusectl (rw,nosuid,nodev,noexec,relatime)
gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
/dev/fuse on /run/user/1000/doc type fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
/home/gsf/fuse/libfuse/build/example/hello on /mnt/fusemnt type fuse.hello (rw,nosuid,nodev,relatime,user_id=0,group_id=0)
二、搭建qemu调试fuse环境
qemu如何运行自己编译的kernel,请参考《linux调试专栏》的其他文章。这里只列出差异化的部分。
1,kenel config需要打开FUSE
kernel source执行make menuconfig:
File systems --->
<*> FUSE (Filesystem in Userspace) support
kernel编译后,qemu启动该kernel,会有/sys/fs/fuse目录。
2,静态编译fuse文件系统
默认采用shared library编译,需要将改成static library方式编译,完整的编译命令如下:
root@linux:/home/gsf/code# git clone https://github.com/libfuse/libfuse.git
root@linux:/home/gsf/code# cd libfuse/; mkdir build; cd build/
root@linux:/home/gsf/code/libfuse/build# meson ..
root@linux:/home/gsf/code/libfuse/build# meson configure --default-library static 配置静态编译
root@linux:/home/gsf/code/libfuse/build# ninja install
root@linux:/home/gsf/code/libfuse/build# cp ../example/hello.c .
root@linux:/home/gsf/code/libfuse/build# gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -static -o hello
可通过在build目录下执行meson configure # list options命令,检查是静态编译还是动态编译,如下图,Current value是动态编译:
如果用动态库方式编译,在qemu kernel中执行hello时则会出错:
# wget http://10.223.11.5/hello
Connecting to 10.223.11.5 (10.223.11.5:80)
saving to 'hello'
hello 100% |********************************| 17736 0:00:00 ETA
'hello' saved
# chmod 777 hello
# ./hello /mnt/fusemnt/
-sh: ./hello: not found
#
3,fuse文件系统拷贝到qemu kernel并挂载
可以通过多种方式在ubuntu宿主机与qemu kernel虚拟机中共享文件,这里用http方式从ubuntu中下载文件然后挂载,在qemu kernel中执行下面命令:
# wget http://10.223.11.5/hello
Connecting to 10.223.11.5 (10.223.11.5:80)
saving to 'hello'
hello 100% |********************************| 2892k 0:00:00 ETA
'hello' saved
# chmod 777 hello
# ./hello /mnt/fusemnt/
#
# mount |grep fuse
hello on /mnt/fusemnt type fuse.hello (rw,nosuid,nodev,relatime,user_id=0,group_id=0)
#