http://www.ruanyifeng.com/blog/2011/12/inode.html

先看看Inode的结构图
 
 
 
 
 
 

再来了解一下文件系统如何存取文件的

1、根据文件名,通过Directory里的对应关系,找到文件对应的Inode number
2、再根据Inode number读取到文件的Inode table
3、再根据Inode table中的Pointer读取到相应的Blocks

这里有一个重要的内容,就是Directory,他不是我们通常说的目录,而是一个列表,记录了一个文件/目录名称对应的Inode number。如下图

 
 
 
 
 
Directory:
A directory is a mapping between the human name for the file and the computer's inode number.
所以说,这个Directory不是文件,我们可以看作是文件系统中的一个属性,只是用来关键文件名与Inode number。这个一定要理解好,否则后面关于硬链接的内容,就不容易理解了。

我在一天一点学习Linux之文件与目录权限的基本概念中讲到
第二栏表示的是有多少文件连接到inode
如果是一个文件,此时这一字段表示这个文件所具有的硬链接数, 
如果是一个目录,则此字段表示该目录所含子目录的个数。

现在是不是容易理解了?如果你还不是很明白,那么下面我们就再通过实例让大家明白。

我们以RHEL6系统为例

在根目录下创建一个test目录,我们进入此目录,进行操作。
[root@yufei test]# pwd
/test
[root@yufei test]# touch testfile
[root@yufei test]# mkdir testdir
创建实验文件和目录
[root@yufei test]# ls -li
total 4
977 drwxr-xr-x. 2 root root 4096 Apr  5 16:48 testdir
976 -rw-r--r--. 1 root root    0 Apr  5 16:47 testfile
查看到文件与目录的Inode和inode count分别为
977 <-----> 2 <-----> testdir
976 <-----> 1 <-----> testfile
现在目录的链接数为2,文件的链接数为1。为什么会这样呢?其实很好理解。对于目录而言,每个目录里面肯定会有两个特殊目录,那就是.和..这两个目录,我们前面的课程中也讲到,.表示当前的目录,而..则是表示上层目录。我们也知道,在Linux系统中,是从根来开始查找的,要想找到某个目录,必需要先找到他的上层目录,所以说,空目录(严格的来说,不能叫空目录)是有两个链接到相应的Inode number的。作为文件很明显,他只有一个链接到相应的Inode number。也不用多说,

下面我们就来看看这个链接数是如何改变的。
继续上面的操作
[root@yufei test]# ln testfile testfile.hard
[root@yufei test]# ln -s testfile testfile.soft
对testfile建立一个硬链接和一个软链接
[root@yufei test]# ls -il
total 4
977 drwxr-xr-x. 2 root root 4096 Apr  5 16:48 testdir
976 -rw-r--r--. 2 root root    0 Apr  5 16:47 testfile
976 -rw-r--r--. 2 root root    0 Apr  5 16:47 testfile.hard
978 lrwxrwxrwx. 1 root root    8 Apr  5 17:03 testfile.soft -> testfile
再查看文件和目录的属性,我们就发现:创建一个硬链接后,testfile的inode count增加了一个。而且testfile和testfile.hard这两个的Inode number是一样的。这个硬链接就是重新创建了一个文件名对应到原文件的Inode。实质就是在Directory中增加了一个新的对应关系。通过这个例子,你是不是更清楚了,这个Inode count的含义了。他就是指,一个Inode对应了多少个文件名。

下面我们再来看看硬链接的其他特点

[root@yufei ~]# watch -n 1 "df -i;df"
Every 1.0s: df -i;df                            Tue Apr  5 21:52:53 2011

Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/sda1             960992  105415  855577   11% /
tmpfs                  63946       1   63945    1% /dev/shm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             15118728   2747612  11603116  20% /
tmpfs                   255784         0    255784   0% /dev/shm
用上面的命令可以实时查看系统中所剩的block和inode的变化数量。
建议大家不要用deumpe2fs和tune2fs这两个命令,如果使用他们来查看的话,将会很郁闷——你会发现,你无论怎么创建文件或对文件写入内容,Inode和block的值都不会变,除非你每操作一次,重新启动一次系统,而用了上面的命令,就是第秒钟监视他们的变化情况。关于df的命令使用,大家可以自行查看帮助进行学习。当然还有du这个命令,他们都和文件系统有关。

我们再来创建一个硬链接
[root@yufei test]# ls -li
total 4
977 drwxr-xr-x. 2 root root 4096 Apr  5 16:48 testdir
976 -rw-r--r--. 2 root root    0 Apr  5 16:47 testfile
976 -rw-r--r--. 2 root root    0 Apr  5 16:47 testfile.hard
978 lrwxrwxrwx. 1 root root    8 Apr  5 17:03 testfile.soft -> testfile
[root@yufei test]# ln testfile testfile.hard1
[root@yufei test]# ls -li
total 4
977 drwxr-xr-x. 2 root root 4096 Apr  5 16:48 testdir
976 -rw-r--r--. 3 root root    0 Apr  5 16:47 testfile
976 -rw-r--r--. 3 root root    0 Apr  5 16:47 testfile.hard
976 -rw-r--r--. 3 root root    0 Apr  5 16:47 testfile.hard1
978 lrwxrwxrwx. 1 root root    8 Apr  5 17:03 testfile.soft -> testfile
可以再观察一下Inode count和Inode number的对应关系。
下面再看看inodes和blocks的变化
[root@yufei ~]# watch -n 1 "df -i;df"
Every 1.0s: df -i;df                            Tue Apr  5 21:53:38 2011

Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/sda1             960992  105415  855577   11% /
tmpfs                  63946       1   63945    1% /dev/shm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             15118728   2747612  11603116  20% /
tmpfs                   255784         0    255784   0% /dev/shm
我们发现,inodes和blocks是没有减少的,所以说,硬链接是不会占用磁盘的空间的。
如果说删除硬链接的话,就会改变Inode count的数量。硬链接还有其他的两个特性:不能跨Filesystem也不能link目录。

下面再来看看这个软链接

[root@yufei test]# ls -il testfile.soft testfile
976 -rw-r--r--. 3 root root 0 Apr  5 21:50 testfile
978 lrwxrwxrwx. 1 root root 8 Apr  5 21:52 testfile.soft -> testfile
他的Inode number和原文件不一样。而且大小也发生了变化。可见,这个软链接是重新建立了一个文件,而文件是指向到原文件,而不是指向原Inode。当然他会占用掉 inode 与 block。当我们删除了源文件后,链接文件不能独立存在,虽然仍保留文件名,但我们却不能查看软链接文件的内容了。但软链接是可以跨文件系统,而且是可以链接目录。他就相当于windows系统下的快捷方式一样。通过这个特性,我们可以通过软链接解决某个分区inode conut不足的问题(软链接到另一个inode count足够多的分区)。

接下来,我们再来分析一下复制文件、移动文件和删除文件对inode的影响

[root@yufei ~]# watch -n 1 "df -i;df"
Every 1.0s: df -i;df                            Tue Apr  5 21:57:38 2011

Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/sda1             960992  105415  855577   11% /
tmpfs                  63946       1   63945    1% /dev/shm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             15118728   2747612  11603116  20% /
tmpfs                   255784         0    255784   0% /dev/shm

[root@yufei test]# ls -li
total 4
977 drwxr-xr-x. 2 root root 4096 Apr  5 16:48 testdir
976 -rw-r--r--. 3 root root    0 Apr  5 18:54 testfile
976 -rw-r--r--. 3 root root    0 Apr  5 18:54 testfile.hard
976 -rw-r--r--. 3 root root    0 Apr  5 18:54 testfile.hard1
978 lrwxrwxrwx. 1 root root    8 Apr  5 17:03 testfile.soft -> testfile
我们先记录以上的信息

先看复制文件的情况
[root@yufei test]# cp testfile testfile.cp
[root@yufei test]# ls -li
976 -rw-r--r--. 3 root root    0 Apr  5 21:50 testfile
979 -rw-r--r--. 1 root root    0 Apr  5 21:58 testfile.cp
我们只对比这两个文件,发现Inode number不一样,我们再来看看inodes和blocks的剩余情况
Every 1.0s: df -i;df                            Tue Apr  5 22:02:49 2011

Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/sda1             960992  105416  855576   11% /
tmpfs                  63946       1   63945    1% /dev/shm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             15118728   2747620  11603108  20% /
tmpfs                   255784         0    255784   0% /dev/shm
发现inodes减少了一个,而blocks也少了,这就说明,复制文件是创建文件,并占Inode和Block的。
文件创建过程是:先查找一个空的Inode,写入新的Inode table,创建Directory,对应文件名,向block中写入文件内容

关于移动文件和删除文件的实验,大家可以自己动手来实践吧。我直接给出相应的说明。
移动文件,他分两种情况:
在同一个文件系统中移动文件时
创建一个新的文件名和Inode的对应关系(也就是在Directory中写入信息),然后在Directory中删除旧的信息,更新CTIME,其他的信息如Inode等等均无任何影响

在不同文件系统移动文件时
先查找一个空的Inode,写入新的Inode table,创建Directory中的对应关系,向block中写入文件内容,同时还会更改CTIME。

删除文件
他实质上就是减少link count,当link count为0时,就表示这个Inode可以使用,并把Block标记为可以写,但并没有清除Block里面数据,除非是有新的数据需要用到这个block。

最后我们来做个总结:

1、一个Inode对应一个文件,而一个文件根据其大小,会占用多块blocks。
2、更为准确的来说,一个文件只对应一个Inode。因为硬链接其实不是创建新文件,只是在Directory中写入了新的对应关系而已。
3、当我们删除文件的时候,只是把Inode标记为可用,文件在block中的内容是没有被清除的,只有在有新的文件需要占用block的时候,才会被覆盖。

 
 
附录:kernel部分inode数据结构列表
                、*
*索引节点对象由inode结构体表示,定义文件在linux/fs.h中
*/
struct inode {
        struct hlist_node       i_hash;              /* 哈希表 */
        struct list_head        i_list;              /* 索引节点链表 */
        struct list_head        i_dentry;            /* 目录项链表 */
        unsigned long           i_ino;               /* 节点号 */
        atomic_t                i_count;             /* 引用记数 */
        umode_t                 i_mode;              /* 访问权限控制 */
        unsigned int            i_nlink;             /* 硬链接数 */
        uid_t                   i_uid;               /* 使用者id */
        gid_t                   i_gid;               /* 使用者id组 */
        kdev_t                  i_rdev;              /* 实设备标识符 */
        loff_t                  i_size;              /* 以字节为单位的文件大小 */
        struct timespec         i_atime;             /* 最后访问时间 */
        struct timespec         i_mtime;             /* 最后修改(modify)时间 */
        struct timespec         i_ctime;             /* 最后改变(change)时间 */
        unsigned int            i_blkbits;           /* 以位为单位的块大小 */
        unsigned long           i_blksize;           /* 以字节为单位的块大小 */
        unsigned long           i_version;           /* 版本号 */
        unsigned long           i_blocks;            /* 文件的块数 */
        unsigned short          i_bytes;             /* 使用的字节数 */
        spinlock_t              i_lock;              /* 自旋锁 */
        struct rw_semaphore     i_alloc_sem;         /* 索引节点信号量 */
        struct inode_operations *i_op;               /* 索引节点操作表 */
        struct file_operations  *i_fop;              /* 默认的索引节点操作 */
        struct super_block      *i_sb;               /* 相关的超级块 */
        struct file_lock        *i_flock;            /* 文件锁链表 */
        struct address_space    *i_mapping;          /* 相关的地址映射 */
        struct address_space    i_data;              /* 设备地址映射 */
        struct dquot            *i_dquot[MAXQUOTAS]; /* 节点的磁盘限额 */
        struct list_head        i_devices;           /* 块设备链表 */
        struct pipe_inode_info  *i_pipe;             /* 管道信息 */
        struct block_device     *i_bdev;             /* 块设备驱动 */
        unsigned long           i_dnotify_mask;      /* 目录通知掩码 */
        struct dnotify_struct   *i_dnotify;          /* 目录通知 */
        unsigned long           i_state;             /* 状态标志 */
        unsigned long           dirtied_when;        /* 首次修改时间 */
        unsigned int            i_flags;             /* 文件系统标志 */
        unsigned char           i_sock;              /* 可能是个套接字吧 */
        atomic_t                i_writecount;        /* 写者记数 */
        void                    *i_security;         /* 安全模块 */
        __u32                   i_generation;        /* 索引节点版本号 */
        union {
                void            *generic_ip;         /* 文件特殊信息 */
        } u;
};
/*
*索引节点的操作inode_operations定义在linux/fs.h中 
*/
struct inode_operations {
        int (*create) (struct inode *, struct dentry *,int);
        /*VFS通过系统调用create()和open()来调用该函数,从而为dentry对象创建一个新的索引节点。在创建时使用mode制定初始模式*/
        struct dentry * (*lookup) (struct inode *, struct dentry *);
        /*该韩式在特定目录中寻找索引节点,该索引节点要对应于dentry中给出的文件名*/
        int (*link) (struct dentry *, struct inode *, struct dentry *);
        /*该函数被系统调用link()电泳,用来创建硬连接。硬链接名称由dentry参数指定,连接对象是dir目录中ld_dentry目录想所代表的文件*/
        int (*unlink) (struct inode *, struct dentry *);
        /*该函数被系统调用unlink()调用,从目录dir中删除由目录项dentry制动的索引节点对象*/
        int (*symlink) (struct inode *, struct dentry *, const char *);
        /*该函数被系统电泳symlik()调用,创建符号连接,该符号连接名称由symname指定,连接对象是dir目录中的dentry目录项*/
        int (*mkdir) (struct inode *, struct dentry *, int);
        /*该函数被mkdir()调用,创建一个新鲁姆。创建时使用mode制定的初始模式*/
        int (*rmdir) (struct inode *, struct dentry *);
        /*该函数被系统调用rmdir()调用,删除dir目录中的dentry目录项代表的文件*/
        int (*mknod) (struct inode *, struct dentry *, int, dev_t);
        /*该函数被系统调用mknod()调用,创建特殊文件(设备文件、命名管道或套接字)。要创建的文件放在dir目录中,其目录项问dentry,关联的设备为rdev,初始权限由mode指定*/
        int (*rename) (struct inode *, struct dentry *,
                       struct inode *, struct dentry *);
        /*VFS调用该函数来移动文件。文件源路径在old_dir目录中,源文件由old_dentry目录项所指定,目标路径在new_dir目录中,目标文件由new_dentry指定*/
        int (*readlink) (struct dentry *, char *, int);
        /*该函数被系统调用readlink()调用,拷贝数据到特定的缓冲buffer中。拷贝的数据来自dentry指定的符号链接,最大拷贝大小可达到buflen字节*/
        int (*follow_link) (struct dentry *, struct nameidata *);
        /*该函数由VFS调用,从一个符号连接查找他指向的索引节点,由dentry指向的连接被解析*/
        int (*put_link) (struct dentry *, struct nameidata *);
        /*在follow_link()调用之后,该函数由vfs调用进行清楚工作*/
        void (*truncate) (struct inode *);
        /*该函数由VFS调用,修改文件的大小,在调用之前,索引节点的i_size项必须被设置成预期的大小*/
        int (*permission) (struct inode *, int);
        /*该函数用来检查给低昂的inode所代表的文件是否允许特定的访问模式,如果允许特定的访问模式,返回0,否则返回负值的错误码。多数文件系统都将此区域设置为null,使用VFS提供的通用方法进行检查,这种检查操作仅仅比较索引及诶但对象中的访问模式位是否和mask一致,比较复杂的系统,比如支持访问控制链(ACL)的文件系统,需要使用特殊的permission()方法*/
        int (*setattr) (struct dentry *, struct iattr *);
        /*该函数被notify_change调用,在修改索引节点之后,通知发生了改变事件*/
        int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
        /*在通知索引节点需要从磁盘中更新时,VFS会调用该函数*/
        int (*setxattr) (struct dentry *, const char *,
                         const void *, size_t, int);
        /*该函数由VFS调用,向dentry指定的文件设置扩展属性,属性名为name,值为value*/
        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        /*该函数被VFS调用,向value中拷贝给定文件的扩展属性name对应的数值*/
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        /*该函数将特定文件所有属性别表拷贝到一个缓冲列表中*/
        int (*removexattr) (struct dentry *, const char *);
        /*该函数从给定文件中删除指定的属性*/
};

linux ----Inode的结构图的更多相关文章

  1. Linux inode && Fast Directory Travel Method(undone)

    目录 . Linux inode简介 . Fast Directory Travel Method 1. Linux inode简介 0x1: 磁盘分割原理 字节 -> 扇区(sector)(每 ...

  2. Linux inode空间占满 “no space left on device”

    Linux inode空间占满 提示 “no space left on device” 中文环境:“无法创建XXX目录,设备没有空间” Linux系统iNode耗尽硬盘无法写入文件怎么办?df -h ...

  3. Linux inode 之我见

    Linux硬盘组织方式为:引导区.超级块(superblock),索引结点(inode),数据块(datablock),目录块(diredtory block).其中超级块中包含了关于该硬盘或分区上的 ...

  4. linux inode已满解决方法

    今天login server的一个网站,发现login后没有生成session.根据以往经验,一般是空间已满导致session文件生成失败. df -h Filesystem Size Used Av ...

  5. Linux inode与文件系统关系

    inode只有在linux文件系统的概念(ext3,ext4) .inode节点数量与文件存储的关系. 二.在文件系统初始化时设置合适的节点数量. linux服务器在存储文件小而数量多的情况下,需要考 ...

  6. linux inode 详解 / 线上inode爆满解决方案

    本文大量参考阮一峰大神博客,整理笔记 之所以写inode文章是由于一次线上问题,引发对inode深入的思考. 磁盘的inode监控与磁盘空间的监控同等重要,线上服务器一定要做好磁盘inode与磁盘空间 ...

  7. 深入浅出理解linux inode结构

    一.inode是什么? 参考文档:http://tech.diannaodian.com/dw/lin/2012/0112/154629.html 做Android底层驱动或者嵌入式Linux的程序猿 ...

  8. 深入浅出理解linux inode结构【转】

    本文转载自:https://blog.csdn.net/fantasyhujian/article/details/9151615 一.inode是什么? 参考文档:http://tech.diann ...

  9. Linux inode 详解

    操作系统的文件数据除了实际内容之外,通常含有非常多的属性,例如Linux操作系统的文件权限与文件属性.文件系统通常会将这两部分内容分别存放在inode和block中. inode 和 block 概述 ...

随机推荐

  1. 各浏览器Cookie大小、个数限制

    一.浏览器允许每个域名所包含的cookie数: Microsoft指出InternetExplorer8增加cookie限制为每个域名50个,但IE7似乎也允许每个域名50个cookie. Firef ...

  2. VC 项目支撑文件解释

    1.解决方案文件:   a.sln 解决方案.把项目中的所有元素或者多个项目整合到一个解决方案中去. b.suo 解决方案定制项.存储用户级别对解决方案的定制,比如打开状态,断点信息.   这两个文件 ...

  3. HJA的异或值

    HJA的异或值 查看 提交 统计 提问 总时间限制:  20000ms 内存限制:  512000kB 描述 形态形成场(Morphogenetic Field)假说是Rupert Sheldrake ...

  4. bzoj 1257: [CQOI2007]余数之和sum 数学 && 枚举

    1257: [CQOI2007]余数之和sum Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1779  Solved: 823[Submit][Sta ...

  5. Javascript禁止网页复制粘贴效果,或者复制时自动添加来源信息

    一.禁止复制 使用方法:在oncopy事件中return false oncopy="return false;" 1.禁止复制网页内容 <body oncopy=" ...

  6. 并行HASH JOIN小表广播问题

    SQL语句: SELECT /*+parallel(t1 16)*/ T1.DATA_DATE, T1.ACCT_NO, T1.ACCT_ORD, T1.ACCT_NO_PK, T1.ACCT_BAL ...

  7. WITH AS 优化逻辑读

    SQL> select * from fxqd_list_20131115_new where (acct_no, oper_no, seqno, trans_amt) not in (sele ...

  8. 【HDOJ】3549 Flow Problem

    网络流基础题目,Edmonds_Karp可解. /* 3549 */ #include <iostream> #include <string> #include <ma ...

  9. Node.js权威指南 (4) - 模块与npm包管理工具

    4.1 核心模块与文件模块 / 574.2 从模块外部访问模块内的成员 / 58 4.2.1 使用exports对象 / 58 4.2.2 将模块定义为类 / 58 4.2.3 为模块类定义类变量或类 ...

  10. 宝洁HR

    宝洁HR系统的测试犯了很多错误 1 最基本也是最弱智的错误:测试根本不仔细,多轮测试后仍然会发现前几轮应该发现的bug. 纠结测试不仔细的原因 a 个人工作坏习惯  老是认为理所当然,对于一些内容,总 ...