最近再看libfuse的文档,有一篇文档doc/how-fuse-works,里面讲到fuse如何mount。
When your user mode program calls fuse_main() (lib/helper.c),
fuse_main() parses the arguments passed to your user mode program,
then calls fuse_mount() (lib/mount.c).
fuse_mount() creates a UNIX domain socket pair, then forks and execs
fusermount (util/fusermount.c) passing it one end of the socket in the
FUSE_COMMFD_ENV environment variable.
fusermount (util/fusermount.c) makes sure that the fuse module is
loaded. fusermount then open /dev/fuse and send the file handle over a
UNIX domain socket back to fuse_mount().
fuse_mount() returns the filehandle for /dev/fuse to fuse_main().
fuse_main() calls fuse_new() (lib/fuse.c) which allocates the struct
fuse datastructure that stores and maintains a cached image of the
filesystem data.
创建一个unix domain socket对,然后fork、execv一个fusermount进程,这个进程打开/dev/fuse,执行mount,然后将文件描述符发送给父进程。在我的现有知识体系里面,只有子进程继承父进程的文件描述符。没有想到子进程还可以发送文件描述符给父进程,当时懵了。
当使用strace抓取系统调用时,发现:
[pid 941687] sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0", iov_len=1}], msg_iovlen=1, msg_control=[{cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, cmsg_data=[4]}], msg_controllen=20, msg_flags=0}, 0) = 1
是不是linux内核有相关的点实现此功能呢,搜索一下,果然有,就是这个SCM_RIGHTS。
Ancillary messages
Ancillary data is sent and received using sendmsg(2) and recvmsg(2).
For historical reasons the ancillary message types listed below are
specified with a SOL_SOCKET type even though they are AF_UNIX specific.
To send them set the cmsg_level field of the struct cmsghdr to
SOL_SOCKET and the cmsg_type field to the type. For more information
see cmsg(3).
SCM_RIGHTS
Send or receive a set of open file descriptors from another
process. The data portion contains an integer array of the file
descriptors. The passed file descriptors behave as though they
have been created with dup(2).
参考
https://blog.cloudflare.com/know-your-scm_rights
man 7 unix, Ancillary messages