不识庐山真面目,只缘身在此山中。—我们面对的计算机
- 块设备
- UNIX的块设备
块设备
块设备将信息存储在固定大小的块中,每个块都有自己的地址。
数据块的大小通常在512字节到32768字节之间。
块设备的基本特征是每个块都能独立于其它块而读写。磁盘是最常见的块设备。
------来自百度百科
块设备是对外部存储设备的一种抽象。
计算机五大部件中的存储部件,是由内存与外存构成的。这是不得以而为之的——内存由晶体管电路构成,存在断电内容消失的问题。所以计算机设计者设计了其他设备完成断电数据保存的任务。这种设备被称为外存。外存可以由其他许多方式构成,磁介质是最常用的一种方式。硬盘,以及以前使用的软盘都是使用磁介质这种方式的。而外存由于构造方式的不同,也有了一个巨大的优势,每个位的价格低了,所以可以构建比内存更大的存储空间。当内存达到4G容量时,相配套的硬盘容量已经到1T了。断电保存,更大的存储空间,是外存相对于内存的优点,而外存相对于内存的缺点也十分突出。
访问速度慢。如果数据从内存中读取,需要50-200个周期,而如果存储在磁盘上,需要大约几千万个周期。而数据读取写入又是大多数程序基本常用的功能。所以我们的计算机的速度限制很大的部分在于外存的速度将整个计算机运行速度拖慢。所以操作系统的设计者使用优秀的缓存算法,优秀的调度算法,希望减少访问外存的次数。
重复读取容易造成设备损坏。对于固态硬盘,在大约进行100 000次重复写之后,块就会磨损坏。一旦块磨损坏之后,就不能再使用了。所以在使用固态硬盘时,会为其设计特殊的文件系统,文件系统保证使用时减少对每个块的使用次数。
由于访问速度慢所以导致了硬件设计者给我们使用外存的接口是以块为单位的,最小的是512字节。这减少了读取写入外存设备的次数。
外部存储设备可以由许多方式构成,同种方式也可以构成不同设备,比如硬盘,软盘。同种设备也可以设计不同的接口。所以UNIX使用了块设备的概念。每种外部存储设备,都存在块的概念,比如硬盘的扇区。块的大小通常在512字节到32768字节之间。而外部存储设备有大量的块,每个块可以单独读取写入。而UNIX的块设备将外部存储设备统一看成是字节的一维数组。可以在随机位置读取随机的字节,只要在数组范围内。这是一种进一步的抽象。
许多人在使用块设备时是使用构建在其之上的文件系统,读取或者写入文件。有些人会认为块设备也是输入输出设备,这是一个概念级的错误。输入设备是完成外界事物数据数字化的设备,而输出设备完成数字转化为外界事物的设备。而块设备是存储体系的一部分,虽然有读取写入的行为,但其任务是完成数据的持久化。不在于信息转换。
《深入理解计算机系统》一书中对存储器系统有如下描述
存储器系统是一个具有不同容量,成本和访问时间的存储设备的层次结构。
各种原因导致了存储系统的形成,而人们也在尽量的完善存储器系统。
基本使用的块设备有硬盘,U盘,固态硬盘,软盘,光盘。
UNIX的块设备
UNIX对外存设备提出抽象,提出块设备的概念。
我们面对的不是各种不同使用方式的物理设备,我们面对的是统一的认为是一个字节一维数组的设备,你可以从任意位置读取写入任意字节,只要在数组的范围之内。
操作块设备使用open read write lseek close接口操作块设备。
linux继承自UNIX,使用统一的接口操作块设备。不同与为每种设备写单独的系统调用,统一的方式使使用者可以快速了解所有块设备的操作。对编写者来说,也可以使代码写的更优雅,更简单。(UNIX的最大的优点是简单)
打开块设备(打开后的文件的偏移是64位的,所以目前的块设备都可以跳转,读取,不过要使用llseek)
int open(constchar*pathname,intflags,mode_tmode);
读取块设备
ssize_t read(int fd, void *buf, size_t count);
写入块设备
ssize_t write(int handle, void *buf, int nbyte);
跳转--支持64位跳转的系统调用,glibc中不能直接调用,需要用另外的包装函数。
int _llseek(unsigned int fd, unsigned long offset_high,unsigned long offset_low, loff_t *result,unsigned int whence);---系统调用
off64_t lseek64(int fd, off64_t offset, int whence);
关闭块设备
int close(int fd);
//io控制函数,可以获取设备许多信息。
int ioctl(int fd, unsigned long request, ...);
这与操作文件的接口是一致的。
使用该接口,我们可以直接操作设备。而UNIX下对设备的格式化,建立分区,创建文件系统等操作都是使用这些接口完成的。你甚至可以读取块设备分析块设备上的文件系统,改变文件系统的某些数据,完成某个文件的隐藏,一个只有你能够使用命令才能使用的文件,这个文件对其他使用者都是不存在的。
(图片–Linux正在分区)
块设备之上可以建立文件系统。而UNIX可以识别多个文件系统。
我们可以讨论文件系统与块设备的关系。
文件系统是建立在块设备之上的,文件系统使用块设备中许多块保存辅助的数据,辅助的数据使块设备在概念上不在是一个线性的一维数组,而是一棵树,无限递归的文件树。这类似于使用内存构建一棵树,不过文件系统中不是用指针,而是提出了I结点的概念。通过I节点建立起树形结构。
文件系统建立在分区之上,一个硬盘上可以建立多个分区,每个分区上可以建立文件系统。而UNIX将每个分区也看成是块设备,可以直接读取写入。这是对外存的另一个层次的抽象。