序言
每天都在使用文件,也经常碰到磁盘空间满的各种问题,那么文件和磁盘有什么关系?
每次在使用文件的时候,总是可以看到一个缓冲区,为什么要缓冲区?有什么作用?
文件
1、 文件到底是什么
以上都是文件,文件是实实在在存在的吗?
并不是,文件只是磁盘的抽象,文件只是对磁盘的一种建模,文件只是磁盘的一种表现形式,或者叫做。。。人类可读的形式显示。。。
计算机的三大抽象分别是,进程是对CPU的抽象,地址空间是对内存的抽象,而文件则是对磁盘的抽象。。。一切皆文件。。。
对于文件来说,你每次open一个文件,其实只不过是打开了一个文件描述符,再换一句话来说,其实就是一堆磁盘的地址,这些地址都指向磁盘的某个位置,然后磁盘里面存储了真正的值。
2、 文件的发展
文件的由来,是为了持久化的保存信息,不依赖于进程(进程消失内容消失),不依赖于内存(断电,内存重新加载),从而我们都认为文件是一种持久化的存在,从而造成了一种错觉,以为文件是真实存在的,然而,所有的内容都是存储在磁盘之上。
文件存储在磁盘之上,从而在磁盘上怎么存储,最简单的方式就是顺序的存放,一个文件占用多大,从而分配多少个连续的空间进行存储。。。磁盘是块设备,从而是一个块一个块的存储。。。
在使用这种方式的时候,在内存中只要记录两个信息,一个是磁盘的起始位置,一个是文件的大小,从而就可以找到文件。
这种方式,在搜索的时候,速度极快,也就是O(1)的时间复杂度,不依赖磁盘的大写,也不依赖文件的个数,但是这种在文件删除的时候,总是会造成文件空洞;另外一个就是在使用这种存储的时候,文件必须连续的存放,而且要确定文件的大小,才能在磁盘上分配固定大小的空间来存储,从而也就会造成,当你需要编辑一个文件的时候,首先,你要预估这个文件的大小,然后才能真正的写入内容,然而,这种是不现实的。。。
但是,对于这种,非常适合CD-ROM和DVD,因为对于这两种存储来说,大小都是固定的,不会发生改变。
为了改善,从而可以使用链表的形式存储,从而在存储的时候,可以不指定文件的大小,但是这种存储方式下,在链表中必须存储下个磁盘块的地址指针,从而每次存储的时候,每个块都不是存储2的幂次方,而且在进行随机读取或者写入的时候,时间复杂度都是O(n),随着文件的大小增大,查找内容都是线性的时间增长。。。
为了改善搜索的性能和存储块的大小问题,从而可以在内存中存放一个列表,用来存储所有块的指向,从而在磁盘上还是存储了整个块的信息,而且在内存中使用列表,性能很快,但是这种的缺点是,消耗过大的内存,因为要映射所有的快,无论是空闲块还是有数据的块。(假设磁盘大小为1T,每块的大小1K,那么需要十亿的内存,如果每位大小是3个字节表示,那么需要3G的内存,啥事没干,消耗了这么多内存)
为了改善内存的使用量,从而又变成了一种新的数据结构,也就是index-node,也就是我们经常说的inode节点,这种节点里面包含两部的数据,一个是文件的属性,一个则是文件的磁盘块位置。
从而在使用这种形式的时候,在每次使用内存的时候,只要每次加载这个文件的inode即可,从而使用内存的时候,只会正比于打开的文件数量,从而。。。在操作系统层面总是会对进程打开的文件个数进行限制。。。
inode也就是最终的形式,也就是我们经常看到的文件组成。
在如上的内容中,使用-i参数表示inode的节点号,使用stat可以查看到文件的属性,可以看到占用的块的个数。
3、 了解这些能解决什么问题
这个最常见的问题就是inode使用完了只会,会显示磁盘空间不足。。。
听说,你们不喜欢python,对,我就是要用这个。。。
磁盘空间是够的,但是inode数量也是有限的。。。
这个时候,需要备份,只能进行mv了,不能使用cp了,毕竟cp还是需要消耗inode的。。
删除的时候,rm是不可以的~~~使用find,也是不错的命令。。。
4、 缓冲区
当使用方法open一个文件的时候,也就是将相关的inode的数据结构加载进内存之中,但是实际上不会将所有的数据加入内存,这个时候,如果是打开的大文件,因为使用的磁盘块多,从而也会略微占用内存,但是总比一下返回所有的数据好,从而有方法是read和readlines,一个是一行一行的读,一个则是将所有的数据加载进行内存。。。这个时候还要考虑的就是什么时候close文件,占用一个文件的时间太长也不好,如果别的进程也要进行读写呢。。。。
当你直接vim打开一个超大型的文件的时候,这个时候你就可以感受到什么叫卡了,因为会将所有的数据块都复制进内存。。。
由于内存的速度远远大于磁盘的速度,从而需要一个缓冲,在读取数据的时候,其实还是一个字节一个字节的读,但是在使用的时候,一个块放在内存中,再读入一个块,其实就是在缓冲区中进行组装。。。
总结:在使用文件的时候,想着这就是一堆磁盘的地址空间。