【Linux】软硬链接

目录

 一、使用ln指令建立文件的软硬链接

1.1 建立软链接

1.2 建立硬链接

二、对于软硬链接的理解

1.1 对于硬链接的理解

1.2 对于软链接的理解

三、软硬链接的应用场景

3.1 软链接的应用场景

3.2 硬链接的应用场景


我们先不管什么是软硬链接,来实操建立一下软硬链接后再来分析

 一、使用ln指令建立文件的软硬链接

1.1 建立软链接

我们可以使用ln指令加上-s选项来建立文件的软链接:

# ln -s  软连接目标文件的文件名  软连接文件的文件名

【Linux】软硬链接_第1张图片

我们可以看到我们创建了一个软链接:file-soft,该文件的第一个属性为l,表示软连接文件

并且这个软连接的inode编号和目标文件并不相同,因此我们可以先断定该文件是一个独立文件,必有自己的inode属性和内容

1.2 建立硬链接

我们可以使用ln指令来直接建立文件的硬链接:

# ln 硬连接目标文件的文件名  硬连接文件的文件名

【Linux】软硬链接_第2张图片我们可以看到我们创建了一个硬链接:file-hard,这个硬连接的inode编号和目标文件相同,因此我们可以先断定该文件不是独立文件,和目标文件公用一个inode属性和内容

二、对于软硬链接的理解

1.1 对于硬链接的理解

在inode结构体中,有一个联合体,用来记录文件的硬链接的个数:

struct inode {
    umode_t         i_mode;//文件的访问权限(eg:rwxrwxrwx)
    unsigned short      i_opflags;
    kuid_t          i_uid;//inode拥有者id
    kgid_t          i_gid;//inode拥有者组id
    unsigned int        i_flags;//inode标志,可以是S_SYNC,S_NOATIME,S_DIRSYNC等

#ifdef CONFIG_FS_POSIX_ACL
    struct posix_acl    *i_acl;
    struct posix_acl    *i_default_acl;
#endif

    const struct inode_operations   *i_op;//inode操作
    struct super_block  *i_sb;//所属的超级快
    /*
        address_space并不代表某个地址空间,而是用于描述页高速缓存中的页面的一个文件对应一个address_space,一个address_space与一个偏移量能够确定一个一个也高速缓存中的页面。i_mapping通常指向i_data,不过两者是有区别的,i_mapping表示应该向谁请求页面,i_data表示被改inode读写的页面。
    */
    struct address_space    *i_mapping;

#ifdef CONFIG_SECURITY
    void            *i_security;
#endif

    /* Stat data, not accessed from path walking */
    unsigned long       i_ino;//inode号
    /*
     * Filesystems may only read i_nlink directly.  They shall use the
     * following functions for modification:
     *
     *    (set|clear|inc|drop)_nlink
     *    inode_(inc|dec)_link_count
     */
    union {
        const unsigned int i_nlink;//硬链接个数
        unsigned int __i_nlink;
    };
    dev_t           i_rdev;//如果inode代表设备,i_rdev表示该设备的设备号
    loff_t          i_size;//文件大小
    struct timespec     i_atime;//最近一次访问文件的时间
    struct timespec     i_mtime;//最近一次修改文件的时间
    struct timespec     i_ctime;//最近一次修改inode的时间
    spinlock_t      i_lock; /* i_blocks, i_bytes, maybe i_size */
    unsigned short          i_bytes;//文件中位于最后一个块的字节数
    unsigned int        i_blkbits;//以bit为单位的块的大小
    blkcnt_t        i_blocks;//文件使用块的数目

#ifdef __NEED_I_SIZE_ORDERED
    seqcount_t      i_size_seqcount;//对i_size进行串行计数
#endif

    /* Misc */
    unsigned long       i_state;//inode状态,可以是I_NEW,I_LOCK,I_FREEING等
    struct mutex        i_mutex;//保护inode的互斥锁

    //inode第一次为脏的时间 以jiffies为单位
    unsigned long       dirtied_when;   /* jiffies of first dirtying */

    struct hlist_node   i_hash;//散列表
    struct list_head    i_wb_list;  /* backing dev IO list */
    struct list_head    i_lru;      /* inode LRU list */
    struct list_head    i_sb_list;//超级块链表
    union {
        struct hlist_head   i_dentry;//所有引用该inode的目录项形成的链表
        struct rcu_head     i_rcu;
    };
    u64         i_version;//版本号 inode每次修改后递增
    atomic_t        i_count;//引用计数
    atomic_t        i_dio_count;
    atomic_t        i_writecount;//记录有多少个进程以可写的方式打开此文件
    const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
    struct file_lock    *i_flock;//文件锁链表
    struct address_space    i_data;
#ifdef CONFIG_QUOTA
    struct dquot        *i_dquot[MAXQUOTAS];//inode磁盘限额
#endif
    /*
        公用同一个驱动的设备形成链表,比如字符设备,在open时,会根据i_rdev字段查找相应的驱动程序,并使i_cdev字段指向找到的cdev,然后inode添加到struct cdev中的list字段形成的链表中
    */
    struct list_head    i_devices;,
    union {
        struct pipe_inode_info  *i_pipe;//如果文件是一个管道则使用i_pipe
        struct block_device *i_bdev;//如果文件是一个块设备则使用i_bdev
        struct cdev     *i_cdev;//如果文件是一个字符设备这使用i_cdev
    };

    __u32           i_generation;

#ifdef CONFIG_FSNOTIFY
   //目录通知事件掩码
    __u32           i_fsnotify_mask; /* all events this inode cares about */
    struct hlist_head   i_fsnotify_marks;
#endif

#ifdef CONFIG_IMA
    atomic_t        i_readcount; /* struct files open RO */
#endif
    //存储文件系统或者设备的私有信息
    void            *i_private; /* fs or device private pointer */
};

我们每创建一个硬链接都会使其内部数据++,每删除一个硬链接都会使其内部数据--,只有当其内部数据为0时(代表没有文件名指向该inode节点了),这个inode节点才会被删除

所以硬链接的本质是创建一个新的文件名映射一个已经存在的inode

1.2 对于软链接的理解

软链接的文件inode编号和目标文件不一样,但我们来打印看看软链接文件中的内容看看是什么样的:

【Linux】软硬链接_第3张图片

咦?软链接的文件内容和目标文件内容是一样的

这是因为软连接内部文件内容放的是自己所指向的文件的路径

所以打印出来的内容是一模一样的,不过软链接有自己独特的inode而已,是一个独立的文件

三、软硬链接的应用场景

3.1 软链接的应用场景

我们现在来创建一系列连串的目录,再在这个目录里写个程序:

【Linux】软硬链接_第4张图片

【Linux】软硬链接_第5张图片

现在我们回到d1所在目录下:

【Linux】软硬链接_第6张图片

在我们当前路径下想要运行d4目录下的test程序很麻烦,需要加上一连串的目录名:

所以我们可以建立一个软连接来指向d4目录下的test程序:

【Linux】软硬链接_第7张图片

这样子想要在当前目录下运行d4目录下的程序就很方便了:

所以我们可以通过软链接可以快速定位复杂路径下的文件,Windows操作系统下的快捷方式就是利用了这个原理

3.2 硬链接的应用场景

我们来看到Linux下的目录:

【Linux】软硬链接_第8张图片

每个目录下都有.和..这两个标识符,我们来研究研究这两个标识符的inode编号:

【Linux】软硬链接_第9张图片

我们可以看到.这个文件的inode编号和当前目录文件的inode编号完全相同,这说明了每个目录文件都有.这个硬链接指向自己

再来看看..

【Linux】软硬链接_第10张图片

我们可以看到.这个文件的inode编号和当前目录的上级目录文件的inode编号完全相同,这说明了每个目录文件的子目录都有..这个硬链接指向自己

我们创建一个目录时,创建的目录里必有..这个硬链接文件指向上级目录,所以每当我们创建目录时上级目录的硬链接数会加1:

【Linux】软硬链接_第11张图片

我们都知道Linux下的目录时一个多叉树结构,有了..的硬链接加持就可以使每个节点指向上一个节点,形成回溯,最终让用户很自由的切换目录:

【Linux】软硬链接_第12张图片

那这么说Linux下的所有目录都至少有两个硬链接,一个是自己本身一个是.文件

按照这个规律我们可以用目录的总链接数-2,即可得出该目录下有多少子目录

但万一用户自己给目录文件创建硬链接呢?抱歉,操作系统不允许用户自己给目录创建硬链接: 【Linux】软硬链接_第13张图片

因为如果让用户随意创建目录的硬链接文件的话会造成Linux的目录结构形成闭环,形成闭环后可能会造成遍历文件时陷入死循环,所以这是不允许的

那Linux目录的..文件本身不是也是形成了环结构嘛?

这是因为Linux系统可以自我识别..文件,而避免陷入循环,而用户创建文件时文件名是不可控的,操作系统并不能识别


本期到这里就全部结束了,下期见~

你可能感兴趣的:(Linux,linux,运维,文件系统,操作系统)