目录
- 前言
- 1. 理解C语言的缓冲区
- 2. 对文件系统的初认识
- 3. 理解软硬链接
- 1. 软硬链接的特征
- 2.软硬链接的作用
- 4. 理解动静态库
- 5. 总结
前言
对于文件来讲,有打开的在内存中的文件,也有没有打开的在磁盘上文件,上一篇文章讲解的是前者,本篇文章将带大家了解后者!
本章重点:
本篇文章着重讲解在磁盘中的文件的存储方式以及inode相关概念.在这之前会解释C语言缓冲区的概念以及作用,最后会带大家了解软硬链接如何创建,软硬链接的区别,理解动静态库.
1. 理解C语言的缓冲区
缓冲区的本质就是一段内存空间,那么为什么要有缓冲区?讲个例子:
你在深圳大学想要将一本书送给你在哈工大的好友,你会亲自将书带过去给他然后再回云南吗?显然不可能你会去楼下的顺丰快递将书籍让顺丰帮你寄到北京区,你就代表一个用户,而书籍
就是你要发送给其他用户的数据,顺丰就是这个缓冲区.很明显缓冲区有以下性质:
1. 顺丰拿到你的快递立刻发送(立刻刷新)
2. 等累计快递达到一定数量统一发送(行刷新)
3. 或者当快递站放满了再发送快递(满刷新)
行缓存的设备文件: 显示器(关心用户体验)
全缓存的设备文件: 磁盘文件(关心效率)
printf("abcdef");
sleep(5);
return 0;
因为printf后没有\n刷新缓冲区,所以信息不会立刻打印出来,当休眠五秒后程序退出时才会进行刷新缓冲区!
除此之外,既然操作系统只认识文件描述符fd,所以C语言的FILE结构体中一定封装了fd,并且C语言的缓冲区实际上也是在FILE结构体中维护的!也就是说直接使用系统调用去进行输出工作是不会有缓冲区的概念的!
2. 对文件系统的初认识
对于已经在内存中打开的文件来说,它的结构无非就是OS为它创建的struct file,但是对于未打开的文件也就是存储在磁盘上的文件,是怎样管理的呢?
看看关于磁盘结构的剖析图:
磁盘看似是一张盘面,实际上内部分为很多个面,一个面对于一个磁头,这是正视图的磁盘.
再来看看俯视图的磁盘:
对于磁盘的每一个面来说,并不是所有的区域都可以用来存储数据,可以把特定的磁道中特定的扇区看作是一个小数组,此小数组中存储文件的属性内容,一般而言一个扇区的大小是512字节.
所以我们把把整个磁盘文件的管理,细拆分为对一个扇区的管理!!!
块组的基本结构:
- 1.inode Table保存对应文件的属性.每一个inode块都有一个inode编号,也就是说一个文件,一个inode,一个inode编号.
- 2.Block Bitmap是个位图,表示特定的块组是否被使用.
- 3.inode Bitmap也是个位图,表示特定的inode是否被占用.
- 4.Data Blocks存储此文件的内容.
- 5.GDT是块组描述符,表征这个块组有多大,已被使用了多少,有多少个inode,还剩多少个等等.
- 6.SuperBlock保存着文件系统的属性信息,每个块组都会备份一份,里面有每一个块组的信息.
从今往后,要在磁盘中找到一个文件只需: 找到inode编号->分区特定的块组->inode->属性->内容.
那么问题是文件的inode是什么我怎么知道?是的,OS都考虑好了,在文件的目录中,存放着文件名和此文件的inode对应的映射关系,可以通过文件名直接找到inode!!!
3. 理解软硬链接
我们看到,真正找到磁盘上文件的并不是文件名,而是inode. 其实在linux中可以让多个文件名对应于同一个inode,这就是硬链接的原理.
建立软链接,使用指令: ln -s 已存在的文件 要建立的软链接
建立硬链接,使用指令: ln 已存在的文件 要建立的软链接
硬链接是什么呢?
1. 硬链接就是一个文件名和inode的映射关系建立硬链接,就是在指定目录下,添加一个新的文件名和inode number的映射关系!
2. 删除目标文件后可以发现,在硬链接文件中仍然有一套完整的目标文件的属性和内容,可以认为硬链接就是在 重命名!
1. 软硬链接的特征
1.软连接是一个独立的文件,因为有独立的inode number.
软连接的内容:目标文件所对应的路径字符串,类似于windows当中的快捷方式.
2.硬链接不是一个独立的文件,因为你没有独立的inode number,你用的是目标文件的inode.
3.属性中有一列硬链接数.那是文件的磁盘级引用计数:有多少个文件和这个inode number有映射关系.
2.软硬链接的作用
1.软链接的作用:
在linux中就是快捷方式!
当我们要找一个路径很深的文件时,可以进行软链接方便找到并使用那个文件。
2.硬链接的作用:
(1) 构建Linux的相对路径结构,让我们可以使用 . 或 . . 来进行路径定位.
(2)一般用硬链接来做文件备份.
4. 理解动静态库
在Linux中:
- 静态库(.a结尾): 程序在编译链接时就把库的代码链接到可执行程序.
- 动态库(.so结尾): 程序运行时才去链接动态库的代码,动态库的代码是被共享的.
gcc/g++默认使用的动态链接的方式,若想要变为静态链接,在编译时加上-static.
如何写一个自己的库?
.h文件写声明,.c写实现,将.c文件编译成.o文件后,再将所有的.o文件通过指针ar打包成一个库,将这个库和.h文件放在同一目录,别人就能用了.
制作静态库指令: ar -rc libhello.a mymath.o myprintf.o
制作动态库指令: gcc -shared myadd.o myprintf.o -o libhello.so
理解动态库的加载
可执行程序先加载到内存里,运行到调用库函数的地方,发现需要库,此时缺页中断,在让0S去检测库是否加载,若没有加载,就根据路径找到库,再加载进内存,接下来进行映射,映射后就能在地址空间的共享区得到库的起始信息地址,而在正文代码段我们调用的库函数的地址是相对地址,再用这个相对地址+偏移量,就可以在地址空间定位库的位置了。
5. 总结
Linux的基础IO部分已经全部讲解完毕,下一章将进入进程信号的学习.掌握文件的inode相关知识可以更好的帮助我们理解文件在打开和关闭时分别是怎样运作的!