块设备读取,linux 0.11中有三种块设备:软盘、硬盘和内存虚拟盘,这里只描述整体架构逻辑,具体实际读取和硬件相关,而硬件操作只是大体理解,并不是太懂;
首先,Linux中一切皆文件,而对于一个文件,整体操作无非就是open,增删修改、close:
对于块设备的话,整体模型分为三层,一层是用户层,一层是高速缓冲区,一层是块设备数据块;对于用户层来说,他并不是直接操作高速缓冲区,他是没有直接读写高速缓冲区的权限的。对于写操作,他是不会立即进行缓冲块同步到块设备中的,只有在再次读取的时候,才会判断原先从块设备读取到缓冲区的数据是否有被改变,如果改变了就要进行一次同步,此时写入才真正生效,返回缓冲块数据到用户空间;基于这个策略,有了一下实现:
首先open一个块设备文件,基于根目录节点不断解析目录文件最终获取到目标i节点,然后使用一个操作系统中的i节点资源存储该i节点;
对于一个已经open的i节点,读写就是两个系统调用,一个就是read,一个就是write,那么基于i节点中存储的信息即可判断该i节点是否是一个块设备,如果是一个块设备则调用属于块设备的read、write函数;一般来说,对于一个文件的读取是按照byte计算的,先操作用户空间数据,然后将用户空间数据复制到缓冲块,读取的时候再进行真正的写入操作;缓冲块和块设备之间的核心函数就是getblk()和ll_rw_block();一个申请缓冲块资源,一个调用块设备驱动;
首先先来讨论两个数据结构,一个是哈希链表hash_table,一个是自由链表free_list,首先就是哈希链表是已经基于块设备设备号和目标块号进行哈希函数计算后缓冲块的链表;而全部的缓冲块头组成另一个链表,该链表的链表头就是free_list;
getblk()程序中,首先就是对哈希链表进行扫描,查看是否已经存在缓冲块映射了目标块设备的逻辑块,如果已经存在缓冲块缓冲目标块设备的逻辑块的话,那就可以直接返回缓冲块,如果没有映射的缓冲的话,就要从全部缓冲块中找一个空闲的缓冲块,如果没有空闲缓冲块的话,就等待空闲缓冲块出现,然后循环查找;
获取到缓冲块之后就将块设备数据缓冲到缓冲块上,就是ll_rw_block()函数,由于块设备读取过程中需要一定的时间,因此创建了一个缓冲机制将需要块设备驱动执行的操作存储起来,这个机制就是请求项机制,对于每个块设备,都有一个块设备的请求项处理函数和请求项链表,当块设备驱动正在处理一个请求项的时候,新增请求项就会将新增请求项插入到块设备的请求项链表中,然后一个接一个的处理请求项;
而处理请求项的过程中会需要一些等待时间去执行一些硬件操作,这些等待是通过中断来实现的,在整个块设备读写操作过程中,会经历不同的阶段,每个阶段会进行不同的操作,这些都是基于中断机制执行的。不过这部分可以粗略理解一下就是块设备使用驱动处理了一个又一个的请求项;
在请求项处理完毕后,对应的块设备完成读写,此时就解开对应的等待队列,继续向下执行程序;