man 7 inode中文手册及个人理解

中文手册

名称

inode-文件inode信息

说明

    每个文件都有一个inode(index node,索引节点),其中包含有关该文件的元数据。应用程序可以使用stat(2)(或相关调用)或statx(2)检索此元数据,stat(2)返回stat结构,statx(2)返回statx结构。
    以下是通常在文件inode中找到或与之关联的信息,其名称与stat(2)或statx(2)返回的相应结构字段名称一致。

Device where inode resides(inode所在的设备)
    stat.st_dev; statx.stx_dev_minor and statx.stx_dev_major
    每个inode(以及相关文件)都位于文件系统,文件系统位于设备上。设备通过其主ID(标识设备的常规类)和次ID(标识常规类中的特定实例)的组合来标识。

Inode number
    stat.st_ino; statx.stx_ino
    文件系统中的每个文件都有一个唯一的inode编号。Inode编号只保证在文件系统中是唯一的(即,不同的文件系统可能使用相同的Inode编号,这就是硬链接不能跨越文件系统边界的原因)。此字段包含文件的inode编号。

File type and mode
    stat.st_mode; statx.stx_mode
    请参阅下面关于文件类型和模式的讨论。

Link count(链接数)
    stat.st_nlink; statx.stx_nlink
    此字段包含指向文件的硬链接数。使用 link(2) 创建指向现有文件的其他链接。

User ID
    st_uid stat.st_uid; statx.stx_uid
    此字段记录文件所有者的User ID。对于新创建的文件,文件User ID是创建过程的有效用户标识。可以使用chown(2)更改文件的用户标识。

Group ID
    stat.st_gid; statx.stx_gid
    inode记录文件的组所有者的ID。对于新创建的文件,文件组ID是父目录的组ID或创建进程的有效组ID,具体取决于是否在父目录上设置了set-group-ID位(见下文)。可以使用chown(2)更改文件的组ID。

Device represented by this inode(此inode表示的设备)
    stat.st_rdev; statx.stx_rdev_minor and statx.stx_rdev_major
     如果这个文件代表一个设备,那么inode会记录该设备的主ID和次ID。

扫描二维码关注公众号,回复: 12656534 查看本文章

File size
    stat.st_size; statx.stx_size
    此字段以字节为单位给出文件的大小(如果是常规文件或符号链接)。符号链接的大小是它包含的路径名的长度,没有终止的空字节。

Preferred block size for I/O(I/O的首选块大小)
    stat.st_blksize; statx.stx_blksize
    该字段提供“首选”块大小,以提高文件系统I/O效率(以较小的块写入文件可能会导致效率低下的读取-修改-重写)

Number of blocks allocated to the file(分配给文件的块数)
    stat.st_blocks; statx.stx_size
    此字段表示分配给文件的块数,以512字节为单位(当文件有缺陷时,此值可能小于st_size/512)
    POSIX.1标准注意到stat结构的st_blocks成员的单位没有被标准定义。在许多实现中,它是512字节;在一些系统中,使用不同的单位,例如1024。此外,每个文件系统的单位可能不同。

Last access timestamp (atime)
    stat.st_atime; statx.stx_atime
    这是文件的最后访问时间戳。它是通过文件访问来更改的,例如execve(2)、mknod(2)、pipe(2)、utime(2)和read(2)(大于零字节)。其他接口,如mmap(2),可以更新atime时间戳,也可以不更新。
    一些文件系统类型允许以这样一种方式装载:文件和/或目录访问不会导致atime时间戳的更新。(请参阅mount(8)中的noatime、nodiratime和relatime,以及mount(2)中的相关信息)此外,如果使用O_NOATIME标志打开文件,则不会更新atime时间戳;请参阅open(2)。

File creation (birth) timestamp (btime)
    (not returned in the stat structure); statx.stx_btime
    文件的创建时间戳。这是在文件创建时设置的,以后不会更改。
    btime时间戳在UNIX系统上历史上并不存在,而且目前大多数Linux文件系统都不支持它。

Last modification timestamp (mtime)
    stat.st_mtime; statx.stx_mtime
    这是文件的最后一次修改时间戳。它通过修改文件来更新,例如mknod(2)、truncate(2)、utime(2)和write(2)(大于零字节)。此外,目录的mtime时间戳通过在该目录中创建或删除文件而改变。mtime时间戳不会因所有者、组、硬链接数或模式的改变而改变。

Last status change timestamp (ctime)
    stat.st_ctime; statx.stx_ctime
    这是文件的最后状态更改时间戳。它可以通过写入或设置inode信息(即所有者、组、链接数、模式等)来更改。

    XFS、JFS、Btrfs和ext4(自Linux 2.6.23以来)支持纳秒时间戳。ext2、ext3和Reiserfs中不支持纳秒时间戳。为了以纳秒精度返回时间戳,stat和statx结构中的时间戳字段被定义为包含纳秒分量的结构。详见stat(2)和statx(2)。在不支持亚秒时间戳的文件系统上,stat和statx结构中的纳秒字段返回值0。

The file type and mode(文件类型和模式)
    stat.st_mode字段包括文件类型和模式。
    POSIX将对应于掩码S_IFMT(见下文)的stat.st_mode位称为文件类型,将对应于掩码07777(8进制)的12位称为文件模式位,将最低有效9位(0777)称为文件权限位。
    文件类型定义了以下掩码值:

S_IFMT     01700008进制)   文件类型bit字段的位掩码
S_IFSOCK   0140000   socket
S_IFLNK    0120000   符号链接
S_IFREG    0100000   普通文件
S_IFBLK    0060000   块设备
S_IFDIR    0040000   目录
S_IFCHR    0020000   字符设备
S_IFIFO    0010000   FIFO

    因此,要测试常规文件(例如),可以编写:

           stat(pathname, &sb);
           if ((sb.st_mode & S_IFMT) == S_IFREG) {
    
    
               /* Handle regular file */
           }

    由于上述形式的测试是常见的,POSIX定义了额外的宏,以便更简洁地编写符合st_mode中的文件类型的测试:

S_ISREG(m)
    是普通文件嘛?
S_ISDIR(m)
    目录?
S_ISCHR(m)
    字符设备?
S_ISBLK(m)
    块设备?
S_ISFIFO(m)
    FIFO(命名管道)
S_ISLNK(m)
    符号链接?
S_ISSOCK(m)
    socket?

    因此,前面的代码片段可以重写为:

           stat(pathname, &sb);
           if (S_ISREG(sb.st_mode)) {
    
    
               /* Handle regular file */
           }

    如果定义了以下任何功能测试宏,则会提供上述大多数文件类型测试宏的定义:_BSD_SOURCE, _SVID_SOURCE,或 _DEFAULT_SOURCE。此外,如果定义了 _XOPEN_SOURCE ,则会提供除 S_IFSOCK 和 S_ISSOCK() 之外的所有上述宏的定义。
    S_IFSOCK 的定义也可以通过定义值为500或更大的 _XOPEN_SOURCE 或(因为glibc 2.24)同时定义 _XOPEN_SOURCE 和 _XOPEN_SOURCE_EXTENDED 来公开。
    如果定义了以下任何特性测试宏,则 S_ISSOCK() 的定义是公开的:_BSD_SOURCE(在glibc 2.19及更早版本中)、_DEFAULT_SOURCE(在glibc 2.20及更高版本中)、_XOPEN_SOURCE的值为500或更大、_POSIX_C_SOURCE的值为200112L或更大,或(自glibc 2.24以来)通过定义 _XOPEN_SOURCE 和 _XOPEN_SOURCE_EXTENDED。
     st_mode 字段的文件模式组件定义了以下掩码值:

           S_ISUID     04000   set-user-ID bit (see execve(2))
           S_ISGID     02000   set-group-ID bit (see below)
           S_ISVTX     01000   sticky bit (see below)

           S_IRWXU     00700   owner has read, write, and execute permission
           S_IRUSR     00400   owner has read permission
           S_IWUSR     00200   owner has write permission
           S_IXUSR     00100   owner has execute permission

           S_IRWXG     00070   group has read, write, and execute permission
           S_IRGRP     00040   group has read permission
           S_IWGRP     00020   group has write permission
           S_IXGRP     00010   group has execute permission

           S_IRWXO     00007   others (not in group) have read, write, and
                               execute permission
           S_IROTH     00004   others have read permission
           S_IWOTH     00002   others have write permission
           S_IXOTH     00001   others have execute permission

    set-group-ID位(S_ISGID)有几个特殊用途。对于一个目录,它表示BSD语义将用于该目录:在那里创建的文件从目录继承其组ID,而不是从创建进程的有效组ID继承,并且在那里创建的目录也将设置S_ISGID位。对于可执行文件,set-group-ID位导致执行该文件的进程的有效组ID发生改变,如execve(2)所述。对于未设置组执行位(S_IXGRP)的文件,set-group-ID位表示强制文件/记录锁定。
    目录上的粘性位(S_ISVTX)意味着该目录中的文件只能由文件所有者、目录所有者和特权进程重命名或删除。

个人理解

背景:inode在文件系统的位置

    物理硬盘是怎么抽象成文件系统的呢?
    总共经历了3层抽象:
    第一层是从磁盘到分区。每个分区都可以看作是一个独立的磁盘;
    第二层是从分区到块。分区就是磁盘,磁盘上面分好扇区,为每个磁盘块编号,编号可以使系统能够计算磁盘上的每个块,我们可以把磁盘视为一系列块的组合。
在这里插入图片描述
    第三层是从块到3个区域的划分。Unix将这些磁盘块分成了3个部分:超级块,i节点表,数据区。超级块存放文件系统本身的信息,i节点表存放文件属性,数据区存放文件内容。所有的inode节点都有相同的大小,i节点表是这些结构的一个列表。文件系统的每个文件在该表中都有一个inode节点。

示例

    本来想再写点啥,但刚刚发现一篇文章写的挺好,写的挺好的文章,连我俩的例子都差不多,都是按照man 2 stat的示例改的。

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>

int main(int argc, char * argv[])
{
    
    
        struct stat sb;

        if(argc !=  2)
        {
    
    
                fprintf(stderr, "Usage:%s <pathname>\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        if(stat(argv[1], &sb) == -1)
        {
    
    
                perror("stat");
                exit(EXIT_FAILURE);
        }

        printf("File type:    ");

        if ((sb.st_mode & S_IFMT) == S_IFREG) 
        {
    
    
                /* Handle regular file */
                printf("%o, regular file\n",S_IFREG);
                printf("inode %lu\n", sb.st_ino);
                printf("st_mode is  %o\n", sb.st_mode);
        }
        else if (S_ISDIR(sb.st_mode))
        {
    
    
                printf("%o, directory\n",S_IFDIR);
                printf("inode %lu\n", sb.st_ino);
                printf("st_mode is  %o\n", sb.st_mode);
        }
        else if (S_ISCHR(sb.st_mode))
        {
    
    
                printf("%o, character device\n",S_IFCHR);
                printf("inode %lu\n", sb.st_ino);
                printf("st_mode is  %o\n", sb.st_mode);
        }
        else if (S_ISBLK(sb.st_mode))
        {
    
    
                printf("%o, block device\n",S_IFBLK);
                printf("inode %lu\n", sb.st_ino);
                printf("st_mode is  %o\n", sb.st_mode);
        }
        else if (S_ISFIFO(sb.st_mode))
        {
    
    
                printf("%o, FIFO (named pipe)\n",S_IFIFO);
                printf("inode %lu\n", sb.st_ino);
                printf("st_mode is  %o\n", sb.st_mode);
        }
        else
                printf("unknown\n");
}

    在系统中找到一个管道文件,就拿它做实验了

# ll -i /run/initctl  
21784 prw------- 1 root root 0 Jan  8 08:18 /run/initctl

    编译执行

# gcc test.c -o test
# ./test /run/initctl
File type:    10000, FIFO (named pipe)
inode 21784
st_mode is  10600

    第一行的文件类型与man手册中的

S_IFIFO    0010000   FIFO

是一致的,表示管道文件。
    第二行是inode值,与ls结果一致。
    第三行st_mode用8进制表示为10600,其中的10000代表管道文件,0600是0400和0200之和,表示文件拥有者有读写权限。
    累了,就这样吧,就这么多吧。

参考文档

https://man7.org/linux/man-pages/man7/inode.7.html
https://linux.die.net/man/2/stat
https://blog.csdn.net/astrotycoon/article/details/8679676

猜你喜欢

转载自blog.csdn.net/zsx0728/article/details/112303819