查找哪个进程实现了 FUSE 文件系统

查找哪个进程实现了 FUSE 文件系统

如何获取 FUSE 文件系统驱动程序的进程 ID?

例如,我目前在 Linux 机器上安装了两个 SSHFS 文件系统:

$ grep sshfs /proc/mounts
host:dir1 /home/gilles/net/dir1 fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000 0 0
host:dir2 /home/gilles/net/dir2 fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000 0 0
$ pidof sshfs
15031 15007

我如何知道 15007 和 15031 哪个是 dir1,哪个是 dir2?理想情况下,我想自动执行该操作,即运行somecommand /home/gilles/net/dir1并让它显示 15007(或 15031,或“不是 FUSE 安装点”,视情况而定)。

请注意,我正在寻找一个通用答案,而不是特定于 SSHFS 的答案,例如跟踪进程sshfs连接到哪个主机和端口,以及服务器端进程打开了哪些文件 - 这甚至可能根本不可能由于连接共享。

我主要对 Linux 答案感兴趣,但适用于所有支持 FUSE 的系统的通用答案将是理想的。

为什么我想知道:跟踪它的操作,在出现问题时杀死它,等等。

答案1

我认为这是不可能的。原因如下。我采取了简单的方法,即将打开的进程的 pid 添加/dev/fuse到 fusion 在挂载时创建的元数据中struct fuse_conn。然后,我使用该信息pid=在 mount 命令中显示一个字段。该补丁非常简单:

diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 7354dc1..32b05ca 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -402,6 +402,9 @@ struct fuse_conn {
        /** The group id for this mount */
        kgid_t group_id;

+       /** The pid mounting process */
+       pid_t pid;
+
        /** The fuse mount flags for this mount */
        unsigned flags;

diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e8799c1..23a27be 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -554,6 +554,7 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
        struct super_block *sb = root->d_sb;
        struct fuse_conn *fc = get_fuse_conn_super(sb);

+       seq_printf(m, ",pid=%u", fc->pid);
        seq_printf(m, ",user_id=%u", from_kuid_munged(&init_user_ns, fc->user_id));
        seq_printf(m, ",group_id=%u", from_kgid_munged(&init_user_ns, fc->group_id));
        if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
@@ -1042,6 +1043,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)

        fc->release = fuse_free_conn;
        fc->flags = d.flags;
+       fc->pid = current->pid;
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
        fc->max_read = max_t(unsigned, 4096, d.max_read);
def@fractal [6:37] ~/p/linux -- master

我启动了内核,安装了 sshfs,然后运行了 mount:

[email protected]:/tmp on /root/tmp type fuse.sshfs (rw,nosuid,nodev,relatime,pid=1549,user_id=0,group_id=0)

成功?不幸的是,没有:

root      1552  0.0  0.0  45152   332 ?        Ssl  13:39   0:00 sshfs [email protected]:/tmp tmp                                                                

然后我意识到:剩余的 sshfs 进程是创建挂载的进程的子进程。它继承自fd。随着熔丝的实现,我们可以有多个继承自 fd 的进程。我们可以让 fd 在 UNIX 套接字中传递,完全脱离原始进程树。

我们可以获得“谁拥有这个 TCP 端口”信息,因为套接字具有此元数据,并且只需解析 /proc 即可告诉我们该信息。不幸的是,fuse fd 是 上的常规 fd /dev/fuse。除非那个 fd 变得特别,否则我不知道如何实现它。

答案2

ps我认为你可以使用和的组合lsof来获取你想要的信息。

用户空间应用程序似乎总是将安装点参数作为参数。如果您通过 grep 遍历进程列表查找以挂载点作为参数的命令(例如ps -ef | egrep ' <mount>( |$)'),您应该获得所有 FUSE 进程。当然,您也可能会得到其他进程,这些进程碰巧也将安装点作为参数(例如ls <mount>)。如果您获取结果列表并运行它lsof并查找与 开放连接的进程/dev/fuse,您将找到与您的安装点 FUSE 相关的进程。

例如,我的系统上有一个 gvfs FUSE 进程:

gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)

如果我运行一个简单的 shell 命令来完成我所有的ps工作lsof,我会得到如下结果:

~$ for pid in \
     $(ps -ef | egrep ' /run/user/1000/gvfs( |$)' | awk '{print $2}')
   do 
     ps -f -p $(lsof -p "$pid" | fgrep /dev/fuse | awk '{print $2}')
   done
UID        PID  PPID  C STIME TTY          TIME CMD
username  2241  1997  0 Apr25 ?        00:00:00 /usr/lib/gvfs/gvfsd-fuse /run/user/1000/gvfs -f -o big_writes

这似乎是做你想做的事。如果有一个 FUSE 级别的内核接口来告诉您 PID 或文件句柄与挂载点之间的映射,那就太好了,但这似乎不存在。

相关内容