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一样