Linux文件缓冲区,inode,软硬链接

1.文件缓冲区

我先看一下代码:

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

 int main()
 {
         const char * str = "hello 标准输出\n";
         write(1,str,strlen(str));

         printf("%s",str);
         fprintf(stdout,"%s",str);
         fputs(str,stdout);

 }

很显然我们可以看到结果是输出4条“hello 标准输出”。

接下来我们如果关闭 1号文件符,将输出重定向到文件中,但是显示结果却只有一条“hello 标准输出”,很显然这是write系统调用的打印的,那么我们c语言库函数打印的内容呢。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
        close(1);
        int fd = open("log.xtx",O_WRONLY| O_CREAT,0644);
        if(fd < 0)
        {
                perror("open()");
        }
        const char * str = "hello 标准输出\n";
        write(1,str,strlen(str));

        printf("%s",str);
        fprintf(stdout,"%s",str);
        fputs(str,stdout);

        close(fd);

}

 

这里为什么会发生这种现象,当发生重定义是,其实是缓冲策略发生了改变

行缓冲 -> 全缓冲 。

解决这种情况我们可以在打印时,将c语言缓冲区的内容,进行刷新,刷新到内核缓冲区中。

 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 #include<unistd.h>
 #include<sys/types.h>
 #include<sys/stat.h>
 #include<fcntl.h>
 int main()
 {
         close(1);
         int fd = open("log.xtx",O_WRONLY| O_CREAT,0644);
         if(fd < 0)
         {
                 perror("open()");
         }
         const char * str = "hello 标准输出\n";
         write(1,str,strlen(str));

         printf("%s",str);
         fprintf(stdout,"%s",str);
         fputs(str,stdout);

         fflush(stdout);
         close(fd);

 }

        

 用户缓冲区和内核缓冲区的交互流程图如下:

 

 所以我们可以肯定的是在用户缓冲区向内核缓冲区写入时,肯定需要fd,当我们把fd给close()了,就不能像内核缓冲区写入数据了。

我们可以看一下c语言提供的文件操作FILE里的内容

 可以看到FILE里面封装了文件描述符。我们可以打印一下这个文件描述符

 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 #include<unistd.h>
 #include<sys/types.h>
 #include<sys/stat.h>
 #include<fcntl.h>
 int main()
 {
         printf("%d\n",stdin->_fileno);
         printf("%d\n",stdout->_fileno);
         printf("%d\n",stderr->_fileno);
 }

 

可以看出标准输入,标准输出,标准错误,对应的就是0,1,2。 

2.inode

文件是存储在磁盘上,那么文件是怎样存储的,

文件 = 文件内容 + 文件属性

要理解inode就需要了解磁盘是怎样工作的。

 

 我们要找到磁盘上的文件,先要通过磁头找到文件所对应的柱面,然后找到磁道,再找扇区。扇区是磁盘的最小单位,一个扇区是512个字节。我们可以将磁盘想象成线性的结构如图:

 

这只是物理结构上的,但是操作系统要与磁盘进行交互,肯定要对磁盘进行描述。首先操作系统会对磁盘进行分区,比如linux如下图:

 可以看到,这里很多分区,每个分区可能挂载了不同的文件系统。每个分区还会分组,每个组里面记录文件的内容和属性如下图:

我们了解了文件存储的基本原则,下面我们来看看以究竟是怎样存储的

dumpe2fs  /dev/sda2|  more 这条命令可以查看ext2,ext3,ext4文件块组的详细内容

[root@dlqatserver25 linux_system]# dumpe2fs /dev/sda2|more
dumpe2fs 1.43.4 (31-Jan-2017)
Filesystem volume name:   <none>
Last mounted on:          /boot
Filesystem UUID:          d9a0b816-d5f0-4f95-9bd0-cee7a5c9be77
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              65536
Block count:              262144
Reserved block count:     13107
Free blocks:              214058
Free inodes:              65505
First block:              0
Block size:               4096
Fragment size:            4096
Group descriptor size:    64
Reserved GDT blocks:      127
Blocks per group:         32768   //每个组块的block数目
Fragments per group:      32768   
Inodes per group:         8192   //每个块组的inode号数量
Inode blocks per group:   512    //每个inode的大小
Flex block group size:    16
Filesystem created:       Mon Jun 10 03:43:04 2019
Last mount time:          Fri Mar 18 15:48:25 2022
Last write time:          Fri Mar 18 15:48:25 2022
Mount count:              80
Maximum mount count:      -1
Last checked:             Mon Jun 10 03:43:04 2019
Check interval:           0 (<none>)
Lifetime writes:          213 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               256
Required extra isize:     32
Desired extra isize:      32
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      0926cbe1-5cdd-4ee4-bd69-a2b331a4be3a
Journal backup:           inode blocks
Journal features:         journal_64bit
Journal size:             32M
Journal length:           8192
Journal sequence:         0x00000172
Journal start:            1


Group 0: (Blocks 0-32767) csum 0x6656 [ITABLE_ZEROED]
  Primary superblock at 0, Group descriptors at 1-1
  Reserved GDT blocks at 2-128
  Block bitmap at 129 (+129)
  Inode bitmap at 137 (+137)
  Inode table at 145-656 (+145)
  28517 free blocks, 8162 free inodes, 5 directories, 8161 unused inodes
[root@dlqatserver25 linux_system]# dumpe2fs /dev/sda2|more
dumpe2fs 1.43.4 (31-Jan-2017)
Filesystem volume name:   <none>
Last mounted on:          /boot
Filesystem UUID:          d9a0b816-d5f0-4f95-9bd0-cee7a5c9be77
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              65536
Block count:              262144
Reserved block count:     13107
Free blocks:              214058
Free inodes:              65505
First block:              0
Block size:               4096
Fragment size:            4096
Group descriptor size:    64
Reserved GDT blocks:      127
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
Flex block group size:    16
Filesystem created:       Mon Jun 10 03:43:04 2019
Last mount time:          Fri Mar 18 15:48:25 2022
Last write time:          Fri Mar 18 15:48:25 2022
Mount count:              80
Maximum mount count:      -1
Last checked:             Mon Jun 10 03:43:04 2019
Check interval:           0 (<none>)
Lifetime writes:          213 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               256
Required extra isize:     32
Desired extra isize:      32
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      0926cbe1-5cdd-4ee4-bd69-a2b331a4be3a
Journal backup:           inode blocks
Journal features:         journal_64bit
Journal size:             32M
Journal length:           8192
Journal sequence:         0x00000172
Journal start:            1


Group 0: (Blocks 0-32767) csum 0x6656 [ITABLE_ZEROED]
  Primary superblock at 0, Group descriptors at 1-1
  Reserved GDT blocks at 2-128
  Block bitmap at 129 (+129)
  Inode bitmap at 137 (+137)
  Inode table at 145-656 (+145)
  28517 free blocks, 8162 free inodes, 5 directories, 8161 unused inodes
  Free blocks: 4251-32767
  Free inodes: 30, 32-8192
Group 1: (Blocks 32768-65535) csum 0x3c9a [ITABLE_ZEROED]
  Backup superblock at 32768, Group descriptors at 32769-32769
  Reserved GDT blocks at 32770-32896
  Block bitmap at 130 (bg #0 + 130)
  Inode bitmap at 138 (bg #0 + 138)
  Inode table at 657-1168 (bg #0 + 657)
  1979 free blocks, 8191 free inodes, 1 directories, 8191 unused inodes
  Free blocks: 37366-38911, 42988-43007, 61027-61439
  Free inodes: 8194-16384
Group 2: (Blocks 65536-98303) csum 0x74fc [INODE_UNINIT, ITABLE_ZEROED]
  Block bitmap at 131 (bg #0 + 131)
  Inode bitmap at 139 (bg #0 + 139)
  Inode table at 1169-1680 (bg #0 + 1169)
  28301 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes
  Free blocks: 66762-67583, 70825-98303
  Free inodes: 16385-24576
Group 3: (Blocks 98304-131071) csum 0xd59d [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Backup superblock at 98304, Group descriptors at 98305-98305
  Reserved GDT blocks at 98306-98432
  Block bitmap at 132 (bg #0 + 132)
  Inode bitmap at 140 (bg #0 + 140)
  Inode table at 1681-2192 (bg #0 + 1681)
  32639 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes
  Free blocks: 98433-131071
  Free inodes: 24577-32768
Group 4: (Blocks 131072-163839) csum 0xa59d [INODE_UNINIT, ITABLE_ZEROED]
  Block bitmap at 133 (bg #0 + 133)
  Inode bitmap at 141 (bg #0 + 141)
  Inode table at 2193-2704 (bg #0 + 2193)
  24576 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes
  Free blocks: 139264-163839
  Free inodes: 32769-40960
Group 5: (Blocks 163840-196607) csum 0xf4d0 [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Backup superblock at 163840, Group descriptors at 163841-163841
  Reserved GDT blocks at 163842-163968
  Block bitmap at 134 (bg #0 + 134)
  Inode bitmap at 142 (bg #0 + 142)
  Inode table at 2705-3216 (bg #0 + 2705)
  32639 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes
  Free blocks: 163969-196607
  Free inodes: 40961-49152
Group 6: (Blocks 196608-229375) csum 0x229e [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Block bitmap at 135 (bg #0 + 135)
  Inode bitmap at 143 (bg #0 + 143)
  Inode table at 3217-3728 (bg #0 + 3217)
  32768 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes
  Free blocks: 196608-229375
  Free inodes: 49153-57344
Group 7: (Blocks 229376-262143) csum 0x47b1 [INODE_UNINIT, ITABLE_ZEROED]
  Backup superblock at 229376, Group descriptors at 229377-229377
  Reserved GDT blocks at 229378-229504
  Block bitmap at 136 (bg #0 + 136)
  Inode bitmap at 144 (bg #0 + 144)
  Inode table at 3729-4240 (bg #0 + 3729)
  32639 free blocks, 8192 free inodes, 0 directories, 8192 unused inodes
  Free blocks: 229505-262143
  Free inodes: 57345-65536

 下面我们来看看inode bitmap,block bitmap 和inode table,data block的关系

首先我们要存储一个文件,需要操作系统给我们分配inode(文件属性信息)和data block(文件内容)。

inode和data bolck的关系

 而inode bitmap,block bitmap这两个位图,标识对应的inode和block是否被占用。

我们可以看一下linux inode结构体中的数据

struct inode {undefined

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 {undefined

void            *generic_ip;         /* 文件特殊信息 */

} u;

 可以看出inode中确实包含了inode和数据块的对应关系。那么文件名和inode有什么关系呢,操作系统只认识inode,可不认识文件名,文件名是方便用户操作的。文件名与inode的关系如下图:

在Linux下我们创建的一切文件都是在根目录下(/)所以只要有根目录的Inode,就能创建一切文件。 

3 软硬链接

有了Inode了解后,软硬链接就十分简单。

软链接可以理解为windons下的快捷方式。

软链接是创建一个新的inode,该inode保存了链接文件的属性。

硬链接,文件inode一样

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值