df 根据文件名找到挂载点原理

df 根据文件名找到挂载点原理

一、shell命令查看特定文件挂载点
#根据文件名找到对应的挂载点
rlk@rlk:vfs$ df ./stat.c 
Filesystem      1K-blocks     Used Available Use% Mounted on
/dev/sda5      1029518584 18451556 958700644   2% /
#遍历当前系统所有的挂载点相关的信息
rlk@rlk:vfs$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.9G     0  1.9G   0% /dev
tmpfs           391M   41M  350M  11% /run
/dev/sda5       982G   18G  915G   2% /
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/loop0      219M  219M     0 100% /snap/gnome-3-34-1804/66
/dev/loop2       56M   56M     0 100% /snap/core18/2074
/dev/loop3      219M  219M     0 100% /snap/gnome-3-34-1804/72
/dev/loop1       56M   56M     0 100% /snap/core18/2128
/dev/loop4       66M   66M     0 100% /snap/gtk-common-themes/1515
/dev/loop5       33M   33M     0 100% /snap/snapd/12883
/dev/loop6       51M   51M     0 100% /snap/snap-store/547
/dev/loop7       33M   33M     0 100% /snap/snapd/12704
/dev/loop8       51M   51M     0 100% /snap/snap-store/542
/dev/sda1       511M  4.0K  511M   1% /boot/efi
tmpfs           391M   32K  391M   1% /run/user/1000
二、原理剖析

先strace查看系统调用,看看有没有什么线索。

rlk@rlk:vfs$ strace df ./stat.c 
execve("/usr/bin/df", ["df", "./stat.c"], 0x7ffd63a88918 /* 62 vars */) = 0
brk(NULL)                               = 0x5638a5c79000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffcd9b3ba80) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=72115, ...}) = 0
mmap(NULL, 72115, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f5917bd2000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360q\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=2029224, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5917bd0000
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68
mmap(NULL, 2036952, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f59179de000
mprotect(0x7f5917a03000, 1847296, PROT_NONE) = 0
mmap(0x7f5917a03000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f5917a03000
mmap(0x7f5917b7b000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19d000) = 0x7f5917b7b000
mmap(0x7f5917bc6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f5917bc6000
mmap(0x7f5917bcc000, 13528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f5917bcc000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f5917bd1580) = 0
mprotect(0x7f5917bc6000, 12288, PROT_READ) = 0
mprotect(0x5638a5bce000, 4096, PROT_READ) = 0
mprotect(0x7f5917c11000, 4096, PROT_READ) = 0
munmap(0x7f5917bd2000, 72115)           = 0
brk(NULL)                               = 0x5638a5c79000
brk(0x5638a5c9a000)                     = 0x5638a5c9a000
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=14537584, ...}) = 0
mmap(NULL, 14537584, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f5916c00000
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2996, ...}) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2996
read(3, "", 4096)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=613, ...}) = 0
mmap(NULL, 613, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f5917c10000
close(3)                                = 0
#这里获取了文件的struct stat相关信息
stat("./stat.c", {st_mode=S_IFREG|0664, st_size=452, ...}) = 0
openat(AT_FDCWD, "./stat.c", O_RDONLY|O_NOCTTY) = 3
close(3)                                = 0
#这里可以看到df命令打开了/proc/self/mountinfo文件,这个是可以查看所有挂在点的文件
openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "24 29 0:22 / /sys rw,nosuid,node"..., 1024) = 1024
read(3, " rw,nosuid,nodev,noexec,relatime"..., 1024) = 1024
read(3, "/fs/cgroup/perf_event rw,nosuid,"..., 1024) = 1024
read(3, "ore18/2074 ro,nodev,relatime sha"..., 1024) = 1024
read(3, "54 29 8:1 / /boot/efi rw,relatim"..., 1024) = 636
read(3, "", 1024)                       = 0
lseek(3, 0, SEEK_CUR)                   = 4732
close(3)                                = 0
getcwd("/home/rlk/Desktop/vfs", 4096)   = 22
lstat("/home/rlk/Desktop/vfs/stat.c", {st_mode=S_IFREG|0664, st_size=452, ...}) = 0
stat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
uname({sysname="Linux", nodename="rlk", ...}) = 0
statfs("./stat.c", {f_type=EXT2_SUPER_MAGIC, f_bsize=4096, f_blocks=257379646, f_bfree=252766819, f_bavail=239675223, f_files=65437696, f_ffree=65033177, f_fsid={val=[3296162858, 246115465]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_RELATIME}) = 0
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=27002, ...}) = 0
mmap(NULL, 27002, PROT_READ, MAP_SHARED, 3, 0) = 0x7f5917bdd000
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
write(1, "Filesystem      1K-blocks     Us"..., 61Filesystem      1K-blocks     Used Available Use% Mounted on
) = 61
write(1, "/dev/sda5      1029518584 184513"..., 52/dev/sda5      1029518584 18451308 958700892   2% /
) = 52
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

三、/proc/self/mountinfo和struct stat

关于mountinfo各个字段信息解释

rlk@rlk:vfs$ cat /proc/self/mountinfo 
24 29 0:22 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw
25 29 0:5 / /proc rw,nosuid,nodev,noexec,relatime shared:14 - proc proc rw
26 29 0:6 / /dev rw,nosuid,noexec,relatime shared:2 - devtmpfs udev rw,size=1973000k,nr_inodes=493250,mode=755
27 26 0:23 / /dev/pts rw,nosuid,noexec,relatime shared:3 - devpts devpts rw,gid=5,mode=620,ptmxmode=000
28 29 0:24 / /run rw,nosuid,nodev,noexec,relatime shared:5 - tmpfs tmpfs rw,size=400228k,mode=755
29 1 8:5 / / rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro
30 24 0:7 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:8 - securityfs securityfs rw
31 26 0:25 / /dev/shm rw,nosuid,nodev shared:4 - tmpfs tmpfs rw
32 28 0:26 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k
33 24 0:27 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755
34 33 0:28 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:10 - cgroup2 cgroup2 rw,nsdelegate
35 33 0:29 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,xattr,name=systemd
36 24 0:30 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:12 - pstore pstore rw
37 24 0:31 / /sys/fs/bpf rw,nosuid,nodev,noexec,relatime shared:13 - bpf none rw,mode=700
38 33 0:32 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,blkio
39 33 0:33 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,cpu,cpuacct
40 33 0:34 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,memory
41 33 0:35 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,net_cls,net_prio
42 33 0:36 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,cpuset
43 33 0:37 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,hugetlb
44 33 0:38 / /sys/fs/cgroup/rdma rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,rdma
45 33 0:39 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,perf_event
46 33 0:40 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,devices
47 33 0:41 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:24 - cgroup cgroup rw,pids
48 33 0:42 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:25 - cgroup cgroup rw,freezer
49 25 0:43 / /proc/sys/fs/binfmt_misc rw,relatime shared:26 - autofs systemd-1 rw,fd=28,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=26316
50 26 0:20 / /dev/mqueue rw,nosuid,nodev,noexec,relatime shared:27 - mqueue mqueue rw
51 26 0:44 / /dev/hugepages rw,relatime shared:28 - hugetlbfs hugetlbfs rw,pagesize=2M
52 24 0:8 / /sys/kernel/debug rw,nosuid,nodev,noexec,relatime shared:29 - debugfs debugfs rw
53 24 0:12 / /sys/kernel/tracing rw,nosuid,nodev,noexec,relatime shared:30 - tracefs tracefs rw
55 29 7:0 / /snap/gnome-3-34-1804/66 ro,nodev,relatime shared:31 - squashfs /dev/loop0 ro
121 29 7:2 / /snap/core18/2074 ro,nodev,relatime shared:65 - squashfs /dev/loop2 ro
124 24 0:46 / /sys/fs/fuse/connections rw,nosuid,nodev,noexec,relatime shared:67 - fusectl fusectl rw
127 24 0:21 / /sys/kernel/config rw,nosuid,nodev,noexec,relatime shared:69 - configfs configfs rw
130 29 7:3 / /snap/gnome-3-34-1804/72 ro,nodev,relatime shared:71 - squashfs /dev/loop3 ro
133 29 7:1 / /snap/core18/2128 ro,nodev,relatime shared:73 - squashfs /dev/loop1 ro
136 29 7:4 / /snap/gtk-common-themes/1515 ro,nodev,relatime shared:75 - squashfs /dev/loop4 ro
139 28 0:47 / /run/vmblock-fuse rw,relatime shared:77 - fuse.vmware-vmblock vmware-vmblock rw,user_id=0,group_id=0,default_permissions,allow_other
142 29 7:5 / /snap/snapd/12883 ro,nodev,relatime shared:79 - squashfs /dev/loop5 ro
145 29 7:6 / /snap/snap-store/547 ro,nodev,relatime shared:81 - squashfs /dev/loop6 ro
148 29 7:7 / /snap/snapd/12704 ro,nodev,relatime shared:83 - squashfs /dev/loop7 ro
151 29 7:8 / /snap/snap-store/542 ro,nodev,relatime shared:85 - squashfs /dev/loop8 ro
154 29 8:1 / /boot/efi rw,relatime shared:87 - vfat /dev/sda1 rw,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro
157 49 0:49 / /proc/sys/fs/binfmt_misc rw,nosuid,nodev,noexec,relatime shared:89 - binfmt_misc binfmt_misc rw
1643 28 0:56 / /run/user/1000 rw,nosuid,nodev,relatime shared:912 - tmpfs tmpfs rw,size=400224k,mode=700,uid=1000,gid=1000
1675 1643 0:57 / /run/user/1000/gvfs rw,nosuid,nodev,relatime shared:929 - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000
574 1643 0:52 / /run/user/1000/doc rw,nosuid,nodev,relatime shared:532 - fuse /dev/fuse rw,user_id=1000,group_id=1000

 /proc/[pid]/mountinfo (since Linux 2.6.26)
              This file contains information about mounts in the
              process's mount namespace (see mount_namespaces(7)).  It
              supplies various information (e.g., propagation state,
              root of mount for bind mounts, identifier for each mount
              and its parent) that is missing from the (older)
              /proc/[pid]/mounts file, and fixes various other problems
              with that file (e.g., nonextensibility, failure to
              distinguish per-mount versus per-superblock options).

              The file contains lines of the form:

              36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
              (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)

              The numbers in parentheses are labels for the descriptions
              below:

              (1)  mount ID: a unique ID for the mount (may be reused
                   after umount(2)).

              (2)  parent ID: the ID of the parent mount (or of self for
                   the root of this mount namespace's mount tree).

                   If a new mount is stacked on top of a previous
                   existing mount (so that it hides the existing mount)
                   at pathname P, then the parent of the new mount is
                   the previous mount at that location.  Thus, when
                   looking at all the mounts stacked at a particular
                   location, the top-most mount is the one that is not
                   the parent of any other mount at the same location.
                   (Note, however, that this top-most mount will be
                   accessible only if the longest path subprefix of P
                   that is a mount point is not itself hidden by a
                   stacked mount.)

                   If the parent mount lies outside the process's root
                   directory (see chroot(2)), the ID shown here won't
                   have a corresponding record in mountinfo whose mount
                   ID (field 1) matches this parent mount ID (because
                   mounts that lie outside the process's root directory
                   are not shown in mountinfo).  As a special case of
                   this point, the process's root mount may have a
                   parent mount (for the initramfs filesystem) that lies
                   outside the process's root directory, and an entry
                   for that mount will not appear in mountinfo.

              (3)  major:minor: the value of st_dev for files on this
                   filesystem (see stat(2)).

              (4)  root: the pathname of the directory in the filesystem
                   which forms the root of this mount.

              (5)  mount point: the pathname of the mount point relative
                   to the process's root directory.

              (6)  mount options: per-mount options (see mount(2)).

              (7)  optional fields: zero or more fields of the form
                   "tag[:value]"; see below.

              (8)  separator: the end of the optional fields is marked
                   by a single hyphen.

              (9)  filesystem type: the filesystem type in the form
                   "type[.subtype]".

              (10) mount source: filesystem-specific information or
                   "none".

              (11) super options: per-superblock options (see mount(2)).

              Currently, the possible optional fields are shared,
              master, propagate_from, and unbindable.  See
              mount_namespaces(7) for a description of these fields.
              Parsers should ignore all unrecognized optional fields.

              For more information on mount propagation see:
              Documentation/filesystems/sharedsubtree.txt in the Linux
              kernel source tree.

stat查看特定文件的stat信息

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/sysmacros.h>

int main(int argc, char *argv[])
{
	struct stat fstat;
	int ret = 0;

	if (argc != 2) {
		printf("Usage: %s <file path>\n", argv[0]);
		return -1;
	}
	
	ret = stat(argv[1], &fstat);
	if (ret < 0) {
		perror("stat()");
		return -1;
	}

	printf("st_dev = %ld\n", fstat.st_dev);
	printf("%d %d\n", major(fstat.st_dev), minor(fstat.st_dev));
    return 0;
}

#struct stat
struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* Inode number */
    mode_t    st_mode;        /* File type and mode */
    nlink_t   st_nlink;       /* Number of hard links */
    uid_t     st_uid;         /* User ID of owner */
    gid_t     st_gid;         /* Group ID of owner */
    dev_t     st_rdev;        /* Device ID (if special file) */
    off_t     st_size;        /* Total size, in bytes */
    blksize_t st_blksize;     /* Block size for filesystem I/O */
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

    /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

    struct timespec st_atim;  /* Time of last access */
    struct timespec st_mtim;  /* Time of last modification */
    struct timespec st_ctim;  /* Time of last status change */

    #define st_atime st_atim.tv_sec      /* Backward compatibility */
    #define st_mtime st_mtim.tv_sec
    #define st_ctime st_ctim.tv_sec
};

测试结果

rlk@rlk:vfs$ ./a.out stat.c 
st_dev = 2053
8 5

从stat中我们可以解析出,st_dev存的是文件本身存储设备的设备号,也就是硬盘的设备号,然后在moutinfo中去匹配,从而找到文件的挂在点;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值