Chinaunix首页 | 论坛 | 博客
  • 博客访问: 699000
  • 博文数量: 193
  • 博客积分: 1875
  • 博客等级: 上尉
  • 技术积分: 2187
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 23:21
个人简介

有时候,就是想窥视一下不知道的东东,因为好奇!

文章分类

全部博文(193)

文章存档

2024年(9)

2023年(3)

2020年(1)

2019年(1)

2018年(1)

2017年(2)

2016年(69)

2015年(53)

2014年(14)

2013年(1)

2012年(5)

2011年(25)

2010年(9)

分类: LINUX

2016-07-16 22:55:08

内核知识收集
    
1. 概述
    在块设备上的操作,涉及内核中的多个组成部分。下图
    
  系统调用read()读取磁盘上的文件。内核响应步骤如下: 
    a. 系统调用read()传递文件描述符/文件偏移量/读取长度等参数, 触发相应的VFS函数。
     b. VFS确定请求的数据是否已经在缓冲区中, 若数据不在缓冲区中, 确定如何执行读块设备操作。
            内核将大多数最近从块设备读出或写入的数据保存在RAM,所以有时候没必要访问磁盘上的数据。

     c. 内核通过映射层(Mapping Layer)确定数据在物理设备上的位置。由对应文件所在的文件系统(ext4/reiserfs/xfs等)来确定。
            1>内核取得文件所在文件系统的块大小,计算所请求数据块的长度,确证数据所在块号。
            2>映射层调用具体文件系统的函数,访问磁盘节点,根据逻辑块号确定所请求数据在磁盘上的位置。
            3>磁盘也分块,内核须确定数据块(通用块)在磁盘上的块号(磁盘块)。

     d. 内核通过通用块层(Generic Block Layer)在块设备上执行读操作,启动I/O操作, 传输请求的数据。
            1>一个i/o操作只针对一组连续的块,请求的数据不必位于相邻的块中。
            2>通用块层为所有的块设备提供一个抽象视图,隐藏硬件块设备的差异,可用通用数据结构描述。

     e. 内核I/O调度层(I/O Scheduler Layer)根据内核的调度策略, 对等待处理的I/O等待队列排序。
            把物理介质上相邻的数据请求聚集在一起。

     f. 块设备驱动(Block Device Driver)通过向磁盘控制器发送相应的命令,执行真正的数据传输。
   
  这里讲述上面步骤d通用块层的工作过程

       

2. 块设备相关概念
    能够随机访问固定大小数据片(chunk)的设备称为块设备, 这些数据片就称作块。
    最常见的块设备是硬盘,除此之外,还有软盘驱动器、CD-ROM驱动. 
    它们都是以安装文件系统的方式使用的。这也是块设备通常的访问方式。
    a. 扇区(Sectors)
        块设备中最小的可寻址单元是扇区。
        扇区大小一般是2的整数倍,而最常见的大小是512字节。
        扇区的大小是设备的物理属性,扇区是所有块设备的基本单元—块设备无法对比它还小的单元进行寻址和操作,不过许多块设备能够一次传输多个扇区。虽然大多数块设备的扇区大小都是512字节,不过其他大小的扇区也很常见(比如,很多CD-ROM盘的扇区都是2k大小)。若块设备使用的扇区大于512字节,则相应的底层驱动程序负责相应的转换工作。
        
        数据在块设备上的位置由块索引和块内偏移确定。块索引(sector indices)在32或64位系统上的变量类型为sector_t。

    b. 块(Blocks)
        对于硬件设备来说,扇区是基本的数据传输单元;而对于VFS(虚拟文件系统),块(block)是基本的数据传输单元。
        例如,当内核访问文件的数据时,它首先从磁盘上读取一个块,这个块有文件的inode,该块对应于磁盘上一个或多个扇区。

        扇区是块设备的最小可寻址单元, 块不能比扇区还小,只能整数倍于扇区大小。
        另外内核(对有扇区的硬件设备)还要求块大小是2的整数倍,而且不能超过一页的长度。
        所以对块大小的最终要求是,必须是扇区大小的2的整数倍,并且要小于页面大小。所以通常块大小是512字节、1K或4K。
        至于块(block)大小,与具体的硬件设备无关。在块设备上创建文件系统时,管理员可以选择块大小;因此在同一个磁盘上,多个分区可能使用不同的块大小。

    c. 段(Segments)
        每个磁盘I/O操作都是设备上相邻的扇区与内存之间传输数据。
        在大多数情况下,数据的传输通过DMA方式;块设备驱动向磁盘控制器发起命令,触发数据传输; 
        当数据传输结束时,控制器给块设备驱动发送一个中断。
        简单的DMA操作,只能传输磁盘上相邻的扇区。这是物理属性的限制:若磁盘控制器DMA传输在非连续的扇区上,则会导致性能下降;因为在磁盘表面上移动读/写磁头,是相当耗时的工作。
        现在的磁盘控制器支持“分散/聚合”(scatter-gather)DMA操作,这种操作模式下,数据传输可以在多个非连续的内存区域中进行。
        对于每个“分散/聚合”DMA操作,块设备驱动向磁盘控制器发送:
            1>.初始磁盘扇区号和传输的总共扇区数;
            2>.内存区域的描述链表,每个描述都包含一个地址和长度。
        磁盘控制器来管理整个数据传输;例如,在读操作中,控制器从磁盘相邻的扇区上读取数据,然后将数据分散存储在内存的不同区域。
        为了利用“分散/聚合”DMA操作,块设备驱动必须能处理被称为段(segments)的数据单元。
        一个段就是一个内存页面或一个页面的部分,它包含磁盘上相邻扇区的数据。这样一个“分散/聚合”DMA操作可能会涉及多个段。
        在通用块设备层(generice block layer)中,若多个页面在内存中连续,且相应的磁盘数据在磁盘上也相邻,那么可以将多个段合并。合并操作产生的大内存区域称为物理段(physical segment)。
        
3. 通用块设备层
        通用块设备层(Generic Block Layer)是内核的一个组成部分,它处理系统所有对块设备的请求。
        有通用块设备层提供的函数,内核可以方便地做到:
        1>将数据存放在高端内存—仅当CPU访问高端内存的数据时,才将页框映射到内核的线性地址空间, 访问完成后解除映射。
        2>实现零拷贝(zero-copy), 即磁盘数据直接拷贝到用户地址空间, 而不需要先拷贝到内核地址空间。
            实际上是,内核进行I/O数据传输使用的页面被映射到用户进程的地址空间中
        3>管理逻辑卷, 如LVM(Logical Volume Manager)和RAID(Redundant Array of Inexpensive Disks)使用的逻辑卷。
                几个不同块设备上的分区,也可以被看作一个单一的分区
        4>发挥现在的磁盘控制器新特性,如大的磁盘缓存、增强的DMA功能、I/O请求调度等。

     a. bio结构体
        内核中块I/O操作的基本容器由bio结构体表示,它定义在文件include/linux/bio.h中。
        该结构体代表了正在活动的以段(segment)链表形式组织的块I/O操作。
        一个段是一小块连续的内存缓冲区。这样,单个缓冲区就不一定要连续。
        所以使用段来描述缓冲区,即使一个缓冲区分散在内存的多个位置上,bio结构体也能对内核保证I/O操作的执行。
        这样的向量I/O称为分散-聚合I/O。
        
        bio结构体中的主要成员变量都是用来管理I/O操作执行的相关信息的,其中最重要的几个成员变量是bi_io_vecs、bi_vcnt和bi_idx。        下图显示了bio结构体及相关结构体之间的关系。
        
    b. 磁盘和磁盘分区的表示
4. 通用块设备层对请求的处理
阅读(1759) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~