FuseファイルシステムのドライバーのプロセスIDを取得するにはどうすればよいですか?
たとえば、現在、Linuxマシンに2つの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、または必要に応じて「ヒューズマウントポイントではない」)を表示します。
sshfs
プロセスが接続されているホストとポート、サーバー側プロセスが開いているファイルの追跡など、SSHFSに固有の回答ではなく、一般的な回答を探していることに注意してください。接続の共有のため、まったく不可能です。
私は主にLinuxの回答に興味がありますが、Fuseをサポートするすべてのシステムで機能する一般的な回答が理想的です。
なぜ私が知りたいのか:その動作を追跡する、問題が発生した場合にそれを殺すなど。
私はそれが可能だとは思いません。これが理由です。私は、Fuseがマウント時に作成するメタデータ/dev/Fuse
にstruct Fuse_conn
を開くプロセスのpidを追加するという単純なアプローチを採用しました。次に、その情報を使用して、mountコマンドのpid=
フィールドを表示しました。パッチは本当に簡単です:
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から継承しました。 Fuseが実装されているため、fdから継承する多数のプロセスを持つことができます。元のプロセスツリーから完全に外れて、UNIXソケットでfdを渡すことができます。
ソケットにはこのメタデータがあるため、このTCP port '情報を所有する' who 'を取得でき、/ procを解析するだけでその情報がわかります。残念ながら、Fusefdは/dev/Fuse
の通常のfdです。 。そのfdがどういうわけか特別にならない限り、これをどのように実装できるかわかりません。
ps
とlsof
を組み合わせて、必要な情報を取得できると思います。
ユーザースペースアプリケーションは、常にマウントポイントの引数を引数として持っているようです。マウントポイントを引数として持つコマンドを探してプロセスリストをgrepすると(例:ps -ef | egrep ' <mount>( |$)'
)、すべてのFuseプロセスを取得する必要があります。もちろん、引数としてマウントポイントを持っている他のプロセスを取得することもあります(例:ls <mount>
)。結果のリストを取得してlsof
で実行し、/dev/Fuse
への接続が開いているプロセスを探すと、マウントポイントのFuse関連のプロセスが見つかります。
したがって、たとえば、システムにgvfsFuseプロセスがあります。
gvfsd-Fuse on /run/user/1000/gvfs type Fuse.gvfsd-Fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
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
それはあなたが望むことをするようです。 PIDまたはファイルハンドルとマウントポイントの間のマッピングを通知するFuseレベルのカーネルインターフェイスがあればいいのですが、それは存在しないようです。