fuse的mount机制 2 -系统调用mount
经过上一篇的分析,目前已经知道mount函数最终进入到mount.c 中的 int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
而主题函数进入到fuse.c中的 fuse_new_common
这两个函数都会在helper.c中的fuse_setup_common中返回,返回后进入helper.c的 fuse_daemonize 。fuse_daemonize使用 foreground参数也即-f参数。
如果-f参数为真,则进入fuse_daemonize的循环体,否则fuse_daemonize直接返回,然后fuse_setup_common也返回到fuse_main_common,进入fuse_loop_mt循环。
本篇主要研究fuse_kern_mount函数。
1. 该函数调用栈:
fuse_setup_common->
fuse_mount_common(const char *mountpoint,struct fuse_args *args) ->
fuse_mount_compat25(const char *mountpoint, struct fuse_args *args) ->
fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
2. mountpoint就是命令行提供的目录参数。args也是根据命令行的参数生成的,struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 }
在fuse_opt.h
struct fuse_args {
/** Argument count */
int argc;
/** Argument vector. NULL terminated */
char **argv;
/** Is 'argv' allocated? */
int allocated;
};
也在fuse_opt.h
注意,在fuse_setup_common中,将命令行的参数进行了规整,处理出mountpoint和args。mountpoint是挂载点的全路径字符串. 如果命令行是./ssfs dir1 -f , args含有两个字符串,第一个字符串是 ./ssfs,第二个字符串是-osubtype=ssfs
3. fuse_kern_mount首先构建struct mount_opts mo;
struct mount_opts {
int allow_other;
int allow_root;
int ishelp;
int flags;
int nonempty;
int auto_unmount;
int blkdev;
char *fsname;
char *subtype;
char *subtype_opt;
char *mtab_opts;
char *fusermount_opts;
char *kernel_opts;
};
然后调用 fuse_mount_sys(mountpoint, &mo, mnt_opts);函数,这里因为 mo->auto_unmount为真,该函数将返回-2,即fallback to fusermount ,
转而调用fuse_mount_fusermount,这里会调用第一个,并返回3.
fuse_mount_fusermount(mountpoint, &mo, tmp_opts, 1);
注意:fuse_mount_sys中主要是open了/dev/fuse以及使用了mount系统调用。 fuse_mount_fusermount中主要使用 socketpair系统调用。
注意2:fuse_mount_fusermount使用了fork,然后子线程做了一系列操作后_exit了。一个重要操作是 exec_fusermount(argv); argv里包含mountpint以及mount程序名即fusermount。
static void exec_fusermount(const char *argv[])
{
execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv);
execvp(FUSERMOUNT_PROG, (char **) argv);
}
FUSERMOUNT_DIR打印字符串显示的是 /usr/local/bin
FUSERMOUNT_DIR "/" FUSERMOUNT_PROG打印字符串显示的是/usr/local/bin/fusermount
原来c语言里将几个字符串直接放在一起就是连起来!
从这里看来,mount函数最终调用了 fusermount程序,一个自带main函数的程序。该程序的源代码就是 util目录下的fusermount.c
注意:后入如果需要打印到屏幕,需要在fuse_mount_fusermount注销掉改变sdio的代码。
4. fusermount.c最终调用了系统调用mount。
调用栈:
fusermount.c:main ->
mount_fuse(const char *mnt, const char *opts) ->
do_mount(const char *mnt, char **typep, mode_t rootmode,
int fd, const char *opts, const char *dev, char **sourcep, char **mnt_optsp, off_t rootsize) ->
mount(source, mnt, type, flags, optbuf).
在mount_fuse向do_mount传递mnt参数之前,调用了check_perm函数,该函数使用chdir将当前的工作路径改为mnt,然后使用"."即当前路径作为mnt。
后面的几个函数均使用"."作为mnt。
问题:自己写的程序按照上述的方式使用root调用mount,会出现errno=22即EINVAL source had an invalid superblock. 那么,为什么fuse就可以这样掉用mount呢?
经验证,在fuse的mount调用中,可以随意改变source,type,flags变量。改变source和type有时会反映到mount列表,有时却不会。
也可以随便改变mnt变量,但是必须是一个存在可访问的路径,改变mnt变量不会反映到mount列表。
注意:貌似这里的mount返回了-1,errno为19表示filesystemtype not configured in the kernel. 但是不影响程序正确执行,而且,strace监测不到这个mount。继续发现,只要type里设置了fuse或fuse.xx就返回0,source可随意设置。 strace追踪不到的原因是mount在fork的子程序里运行的。
如果使用strace -f可以追中到子进程的mount,然而结果显示Operation not permitted。
使用sudo的话,实际运行的mount代码是fuse_mount_sys函数里的。
fuse的mount机制 2 -系统调用mount的更多相关文章
- fuse的mount机制-流程及参数
在bbfs中,传递的参数有两个目录,fuse将一个目录挂载在另一个目录下. 在ssfs中,传递的参数只有一个目录(传递两个目录fuse会出错). 问题:那么fuse的mount机制到底需要几个目录参数 ...
- mount机制3-/etc/mtab
这次查看fuse_mount_sys函数的执行过程,理解mount的各个阶段. 这个函数能够执行的前提是命令行使用root账户. 1. 首先,该函数仍然是主要使用 mount(const char * ...
- linux系统调用mount全过程分析【转】
本文转载自:https://blog.csdn.net/skyflying2012/article/details/9748133 系统调用本身是软中断,使用系统调用,内核也陷入内核态,异常处理,找到 ...
- [mount]linux 挂载时 mount: wrong fs type, bad option, bad superblock on /dev/sdb
原因:挂载时未格式化,使用的文件系统格式不对 解决方案:格式化 sudo mkfs -t ext4 /dev/sdb 再挂载 sudo mount /dev/sdb /xxx/ 用df -h检查,发现 ...
- Linux文件系统的设计
总论: linux的文件系统设计非常优秀,总的来讲有两大部分,第一部分就是树形的组织结构,第二部分就是vfs,树形的组织结构组织了文件系统的表象,用户非常方便的使用,而vfs是文件系统的实现机理,它处 ...
- linux文件系统调用(1)---mount
术语表: struct mount:挂载点 struct mountpoint:挂载点节点 struct vfsmount:挂载项 源文件系统:用户将要挂载的文件系统 目的文件系统:挂载源文件系统的文 ...
- mount源码分析 【转】
转自:http://blog.chinaunix.net/uid-10769062-id-3230811.html Busybox- 在util-linux/mount.c的line:1609行首先映 ...
- mount
产品,平台,RS6000, pseries 软件版本, aix 当NFS在NFS客户端加载时,系统会问是使用 soft-mount 还是hard-mount, 它们之间有什么区别? 它们的区别在于当发 ...
- mount nfs的可选参数
mount nfs的可选参数:HARD mount和SOFT MOUNT:HARD:NFS CLIENT会不断的尝试与SERVER的连接(在后台,不会给出任何提示信息,在LINUX下有的版本仍然会给出 ...
随机推荐
- Scrapy学习-6-JSON数据处理
使用json模块处理JSON数据 class JsonwithEncodingPipeline(object): def __init__(self): self.file = codecs.open ...
- 有关 GCC 及 JNA 涉及动态库/共享库时处理库文件名的问题
动态库尤其是共享库在 Linux 环境下普遍存在库文件名包含版本号的情况,比如 Linux 环境下经常会发现一个共享库的真实文件名是 libfoo.so.1.1.0,而同时会有多个指向该真实库文件的软 ...
- 解决Linux系统没有/etc/sysconfig/iptables文件
Linux系统中,防火墙默认是不开启的,一般也没有配置过任何防火墙的策略,所以不存在/etc/sysconfig/iptables文件. 一.常规解决方法: 1.在控制台使用iptables命令随便写 ...
- android 获得系统时间
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...
- 使用Myeclipse + SVN + TaoCode 免费实现项目版本控制的详细教程
通过Myeclipse + SVN插件 + TaoCOde可以省去代码仓库的租建:同时还可以很好的满足小团队之间敏捷开发的需求.接下来详细介绍整个搭建流程. 首先,介绍所用到的工具: 1,Myecli ...
- Go -- 通过GOTRACEBACK生成程序崩溃后core文件的方法(gcore gdb)
写一个错误的c程序 package dlsym import "testing" func Test_intercept(t *testing.T) { Intercept(& ...
- Mac电脑解压文件unrar用密码问题解决
下载了一个rar文件,有密码的,你懂的. 但是在mac上面,用unrar解压,只能解出空文件:用izip解压,直接停在那里不动. 只好上网搜索.找到了办法. 用brew 安装了命令行版本的 unrar ...
- SpringCloud中Redis的使用
1.引入redis相关jar包 <dependency> <groupId>org.springframework.boot</groupId> <artif ...
- vijos1308 埃及分数(迭代加深搜索)
题目链接:点击打开链接 题目描写叙述: 在古埃及.人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数.如:2/3=1/2+1/6,但不同意2/3=1/3+1/3,由于加数中有同样的.对于 ...
- TCP socket心跳包示例程序
在做游戏开发时,经常需要在应用层实现自己的心跳机制,即定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性. 在TCP socket心跳机制中,心跳包可以由服务器发送给客户端 ...