strace df -h df命令代码实现研究

/proc/self/fd

/proc/self/fd报告进程打开的文件。每个条目都是一个“神奇”的符号链接,其名称是文件描述符目标是打开的文件。它的神奇之处在于,链接实际上指向文件本身,即使通过调用获得的文件名readlink不是有效的文件名,例如,对于没有名称的文件(例如匿名管道),也会发生这种情况和套接字),并删除文件。

The abbreviation “fd” stands for file descriptor.

 

/system/etc/ld.config

android 的默认动态库的查找路径 /system/etc/ 的ld.config*

 

当运行一个可执行程序的时候,系统根据一个配置文件(/system/etc/ld.config.<vndk_version>.txt),为该程序创建对应的namespace。该配置文件分别定义了/system/bin/、/vendor/bin/等目录下可执行程序在运行时进程内的namespace配置。例如运行/system/bin/目录下的程序时,可执行程序所在的namespace的default_library_path被设置为/system/lib64//product/lib64,即先从这两个目录开始查找依赖的库;而运行/vendor/bin/目录下的程序时,可执行程序所在的namespace的default_library_path被设置为/odm/lib64/vendor/lib64,即先从这两个目录查找依赖的库。

一个namespace可以关联多个其他namespace,当在这个namespace中找不到库文件的时候,可以在其直接关联的namespace中查找,如果仍然找不到,则不再继续。如果一个库文件在其调用者的namespace中找到,则该库也属于调用者的namespace,如果一个库文件在其调用者namespace的关联的某个namespace中找到,则该库属于关联的namespace。

 

 

/proc/mounts

openat(AT_FDCWD, "/proc/mounts", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "/dev/block/dm-4 / ext4 ro,seclab"..., 1024) = 1024

可以看到 df命令终究还是读取的/proc/mounts

 

 

all

If an argument is the absolute file name of a device node containing a mounted file system, df shows the space available on that file system rather than on the file system containing the device node.   This version of df cannot show the space available on unmounted file systems, because on most kinds of systems doing so requires non-portable intimate knowledge of file system structures.

如果参数是一个包含挂载的文件系统的设备节点的绝对文件名,则df显示该文件系统上的可用空间,而不是包含这个设备节点的文件系统上的可用空间。这个版本的df不能显示未挂载的文件系统上的可用空间,因为在大多数类型的系统上,这样做需要对文件系统结构有不可移植的深入了解。

 

       -a, --all
              include pseudo, duplicate, inaccessible file systems

 

/toys/posix/df.c

// getmountlist.c
struct mtab_list {
  struct mtab_list *next, *prev;
  struct stat stat;
  struct statvfs statvfs;
  char *dir;
  char *device;
  char *opts;
  char type[0];
};

 

static void show_mt(struct mtab_list *mt, int measuring)
{
  unsigned long long suap[4], block = 1, ll;
  char *dsuapm[6]; // device, size, used, avail, percent, mount
  int i;

  // If we don't have -a, skip overmounted and synthetic filesystems.
  if (!mt || (!FLAG(a) && (!mt->stat.st_dev || !mt->statvfs.f_blocks))) return;

// 意思是 (假设!mt是0) 如果a是1,!FLAG(a)是0,就继续向下执行不return。

// 如果a是0,!FLAG(a)是1,要继续看stat.st_dev和statvfs.f_blocks

stat.st_dev 0 statvfs.f_blocks 0 return

stat.st_dev 1 statvfs.f_blocks 1 继续向下执行不return

两个中只有一个为0,return

  • st_dev 存的是文件本身存储设备的设备号,也就是硬盘的设备号
  • st_rdev是针对驱动的字符设备和块设备文件的主次设备号

           struct statvfs { 
               unsigned long f_bsize; /* 文件系统块大小 */ 
               unsigned long f_frsize; /* 片段大小 */ 
               fsblkcnt_t f_blocks; /* fs 的大小(以 f_frsize 为单位) */ 
               fsblkcnt_t f_bfree; /* 空闲块数 */ 
               fsblkcnt_t f_bavail; /* 非特权用户的空闲块数

 

// toys.h

#define FLAG(x) (!!(toys.optflags&FLAG_##x))  // Return 1 if flag set, 0 if not

 

在计算机科学中,合成文件系统或伪文件系统是非文件对象的分层接口,这些对象在基于磁盘或长期存储的文件系统的树中看起来好像是常规文件。

https://en.wikipedia.org/wiki/Synthetic_file_system

 

"overmounted filesystems" 指的是在 Unix/Linux 系统中的一种现象,即一个文件系统(通常是指一个挂载点)被另一个文件系统所覆盖(挂载)。这种情况通常发生在管理员试图挂载一个文件系统到一个已经被挂载的目录上的时候。

当一个文件系统被挂载到一个已经有内容的目录上时,原先目录下的内容就会被隐藏,取而代之的是新挂载的文件系统的内容。这种行为可能会导致原先目录下的内容不可见,直到新挂载的文件系统被卸载为止。

 

 

overmounts

看起来如果stat.st_dev相同,就是mount --bind

    // Loop through mount list to filter out overmounts.
    for (mt = mtend; mt; mt = mt->prev) {
      for (mt3 = mt, mt2 = mt->prev; mt2; mt2 = mt2->prev) {
        if (mt->stat.st_dev == mt2->stat.st_dev) {
          // For --bind mounts, show earliest mount
          if (!strcmp(mt->device, mt2->device)) { // 这里的mt->device,即输出的最左边一列
            mt3->stat.st_dev = 0;
            mt3 = mt2;
          } else mt2->stat.st_dev = 0;
        }
      }
    }

 

stat

RMX1901CN:/ $ stat /data/media
  File: /data/media
  Size: 4096     Blocks: 16      IO Blocks: 512 directory
Device: 80dh/2061d   80d是16进制,等于2061十进制    Inode: 5373953  Links: 4
Access: (0770/drwxrwx---)       Uid: ( 1023/media_rw)   Gid: ( 1023/media_rw)
Access: 2024-02-01 14:40:06.201253211 +0800
Modify: 2024-02-13 22:09:43.133999651 +0800
Change: 2024-02-13 22:09:43.133999651 +0800
RMX1901CN:/ $ stat /data
  File: /data
  Size: 4096     Blocks: 16      IO Blocks: 512 directory
Device: 80dh/2061d       Inode: 2        Links: 72
Access: (0771/drwxrwx--x)       Uid: ( 1000/  system)   Gid: ( 1000/  system)
Access: 2024-02-01 14:40:00.721253213 +0800
Modify: 2021-05-04 19:17:23.381922062 +0800
Change: 1970-02-15 07:37:31.019999998 +0800
RMX1901CN:/ $ stat /cache
  File: /cache
  Size: 4096     Blocks: 16      IO Blocks: 512 directory
Device: 80ah/2058d       Inode: 2        Links: 6
Access: (0770/drwxrwx---)       Uid: ( 1000/  system)   Gid: ( 2001/   cache)
Access: 1970-12-28 18:22:14.000000000 +0800
Modify: 2024-02-13 21:54:16.000000000 +0800
Change: 2024-02-13 21:54:16.000000000 +0800

 

//usage:       " %d    Device number in decimal\n"
//usage:       " %D    Device number in hex\n"

 

    } else if (m == 'd') {
        strcat(pformat, "llu");
        printf(pformat, (unsigned long long) statbuf->st_dev);
    } else if (m == 'D') {
        strcat(pformat, "llx");
        printf(pformat, (unsigned long long) statbuf->st_dev);

posted @ 2024-02-17 13:57  hrdom  阅读(41)  评论(0编辑  收藏  举报