文件系统的文件太多,而且是照搬的MINIX的文件系统,不想继续分析下去了。缓冲区机制和文件系统密切相关,所以这里就简单分析一下缓冲区机制。

buffer.c 程序用于对高速缓冲区(池)进行操作和管理。高速缓冲区位于内核代码块和主内存区之间,见图9-9 中所示。高速缓冲区在块设备与内核其它程序之间起着一个桥梁作用。除了块设备驱动程序以外,内核程序如果需要访问块设备中的数据,就都需要经过高速缓冲区来间接地操作。

因为读取磁盘数据很耗费时间,所以缓冲区的作用就是存储读过的磁盘数据,下次有需求直接从缓冲区读取,缓冲区是内存区域,读取非常快速。

图中高速缓冲区的起始位置从内核模块末段end 标号开始,end 是内核模块链接期间由链接程序(ld)设置的一个值,内核代码中没有定义这个符号。当在连接生成system 模块时,ld 程序的digest_symbols()函数会产生此符号。该函数主要用于对全局变量进行引用赋值,并且计算每个被连接文件的其始和大小,其中也设置了end 的值,它等于data_start + datasize + bss_size,也即内核模块的末段。

整个高速缓冲区被划分成1024 字节大小的缓冲块,正好与块设备上的磁盘逻辑块大小相同。高速缓冲采用hash 表和空闲缓冲块队列进行操作管理。在缓冲区初始化过程中,从缓冲区的两端开始,同时分别设置缓冲块头结构和划分出对应的缓冲块。缓冲区的高端被划分成一个个1024 字节的缓冲块,低端则分别建立起对应各缓冲块的缓冲头结构buffer_head(include/linux/fs.h,68 行),用于描述对应缓冲块的属性和把所有缓冲头连接成链表。直到它们之间已经不能再划分出缓冲块为止,见图9-10 所示。而各个buffer_head 被链接成一个空闲缓冲块双向链表结构。详细结构见图9-11 所示。

缓冲区的大致结构可参照buffer.c的buffer_init函数:

extern int end;			// 由连接程序ld 生成的表明程序末端的变量。[??]
struct buffer_head *start_buffer = (struct buffer_head *) &end;
struct buffer_head *hash_table[NR_HASH]; // NR_HASH = 307 项。
static struct buffer_head *free_list; //// 缓冲区初始化函数。
// 参数buffer_end 是指定的缓冲区内存的末端。对于系统有16MB 内存,则缓冲区末端设置为4MB。
// 对于系统有8MB 内存,缓冲区末端设置为2MB。
void
buffer_init (long buffer_end)
{
struct buffer_head *h = start_buffer;
void *b;
int i; // 如果缓冲区高端等于1Mb,则由于从640KB-1MB 被显示内存和BIOS 占用,因此实际可用缓冲区内存
// 高端应该是640KB。否则内存高端一定大于1MB。
if (buffer_end == 1 << 20)
b = (void *) (640 * 1024);
else
b = (void *) buffer_end;
// 这段代码用于初始化缓冲区,建立空闲缓冲区环链表,并获取系统中缓冲块的数目。
// 操作的过程是从缓冲区高端开始划分1K 大小的缓冲块,与此同时在缓冲区低端建立描述该缓冲块
// 的结构buffer_head,并将这些buffer_head 组成双向链表。
// h 是指向缓冲头结构的指针,而h+1 是指向内存地址连续的下一个缓冲头地址,也可以说是指向h
// 缓冲头的末端外。为了保证有足够长度的内存来存储一个缓冲头结构,需要b 所指向的内存块
// 地址 >= h 缓冲头的末端,也即要>=h+1。
while ((b -= BLOCK_SIZE) >= ((void *) (h + 1)))
{
h->b_dev = 0; // 使用该缓冲区的设备号。
h->b_dirt = 0; // 脏标志,也即缓冲区修改标志。
h->b_count = 0; // 该缓冲区引用计数。
h->b_lock = 0; // 缓冲区锁定标志。
h->b_uptodate = 0; // 缓冲区更新标志(或称数据有效标志)。
h->b_wait = NULL; // 指向等待该缓冲区解锁的进程。
h->b_next = NULL; // 指向具有相同hash 值的下一个缓冲头。
h->b_prev = NULL; // 指向具有相同hash 值的前一个缓冲头。
h->b_data = (char *) b; // 指向对应缓冲区数据块(1024 字节)。
h->b_prev_free = h - 1; // 指向链表中前一项。
h->b_next_free = h + 1; // 指向链表中下一项。
h++; // h 指向下一新缓冲头位置。
NR_BUFFERS++; // 缓冲区块数累加。
if (b == (void *) 0x100000) // 如果地址b 递减到等于1MB,则跳过384KB,
b = (void *) 0xA0000; // 让b 指向地址0xA0000(640KB)处。
}
h--; // 让h 指向最后一个有效缓冲头。
free_list = start_buffer; // 让空闲链表头指向头一个缓冲区头。
free_list->b_prev_free = h; // 链表头的b_prev_free 指向前一项(即最后一项)。
h->b_next_free = free_list; // h 的下一项指针指向第一项,形成一个环链。
// 初始化hash 表(哈希表、散列表),置表中所有的指针为NULL。
for (i = 0; i < NR_HASH; i++)
hash_table[i] = NULL;
}

根据上面的理论知识,这段代码很好分析,就不多做解释了。

Linux0.11内核--缓冲区机制大致分析的更多相关文章

  1. Linux0.11内核--系统调用机制分析

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5570691.html ] Linux内核从启动到初始化也看了好些个源码文件了,这次看到kern ...

  2. Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析

    Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /* ...

  3. linux0.11内核源码剖析:第一篇 内存管理、memory.c【转】

    转自:http://www.cnblogs.com/v-July-v/archive/2011/01/06/1983695.html linux0.11内核源码剖析第一篇:memory.c July  ...

  4. Linux0.11内核剖析--内核体系结构

    一个完整可用的操作系统主要由 4 部分组成:硬件.操作系统内核.操作系统服务和用户应用程序,如下图所示: 用户应用程序是指那些字处理程序. Internet 浏览器程序或用户自行编制的各种应用程序: ...

  5. Linux0.11内核--内存管理之1.初始化

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5597705.html ] Linux内核因为使用了内存分页机制,所以相对来说好理解些.因为内存 ...

  6. Linux0.11内核剖析--初始化程序(init)

    1.概述 在内核源代码的 init/目录中只有一个 main.c 文件. 系统在执行完 boot/目录中的 head.s 程序后就会将执行权交给 main.c.该程序虽然不长,但却包括了内核初始化的所 ...

  7. Linux0.11内核源码——内核态线程(进程)切换的实现

    以fork()函数为例,分析内核态进程切换的实现 首先在用户态的某个进程中执行了fork()函数 fork引发中断,切入内核,内核栈绑定用户栈 首先分析五段论中的第一段: 中断入口:先把相关寄存器压栈 ...

  8. linux0.11内核源码——进程各状态切换的跟踪

    准备工作 1.进程的状态有五种:新建(N),就绪或等待(J),睡眠或阻塞(W),运行(R),退出(E),其实还有个僵尸进程,这里先忽略 2.编写一个样本程序process.c,里面实现了一个函数 /* ...

  9. linux0.11内核源码——boot和setup部分

    https://blog.csdn.net/KLKFL/article/details/80730131 https://www.cnblogs.com/joey-hua/p/5528228.html ...

随机推荐

  1. 为什么要学习Linux

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 本篇修改自我在知乎上回答的问题,为什么要学习 Linux? 我最开始用Linux是 ...

  2. AngularJs 动态加载模块和依赖

    最近项目比较忙额,白天要上班,晚上回来还需要做Angular知识点的ppt给同事,毕竟年底要辞职了,项目的后续开发还是需要有人接手的,所以就占用了晚上学习的时间.本来一直不打算写这些第三方插件的学习笔 ...

  3. Lasso回归算法: 坐标轴下降法与最小角回归法小结

    前面的文章对线性回归做了一个小结,文章在这: 线性回归原理小结.里面对线程回归的正则化也做了一个初步的介绍.提到了线程回归的L2正则化-Ridge回归,以及线程回归的L1正则化-Lasso回归.但是对 ...

  4. ubuntu super daemon设置

    super daemon是一个在Linux下面全面管理自己服务设置的东东,他可以接管很多服务的设定,只需要在/etc/xinetd.d/下面放置好自己的配置文件就可以了,那么,具体应该怎么配置呢?   ...

  5. struts2学习笔记--使用struts2插件实现ajax处理(返回json数据)

    贴一个简单的例子,通过jquery的post调用action,定义一个对象User,有name和age属性,实例化几个对象,以json的格式返回到jsp,在前台页面显示出来,模拟用户列表. 导入相关j ...

  6. 教你快速高效接入SDK——服务器端支付回调的处理方式

    转载自:http://blog.csdn.net/chenjie19891104/article/details/48321427今天着重把之前渠道服务器端SDK的时候,遇到的一个蛋疼的问题给解决了. ...

  7. 让你的网站免费支持 HTTPS 及 Nginx 平滑升级

    为什么要使用 HTTPS ? 首先来说一下 HTTP 与 HTTPS 协议的区别吧,他们的根本区别就是 HTTPS 在 HTTP 协议的基础上加入了 SSL 层,在传输层对网络连接进行加密.简单点说在 ...

  8. CentOS下VMware用桥接模式,静态ip上外网

    15年的时候,写过一篇博客:VMware中网络设置之Bridged  也是关于linux下vmware桥接模式.静态ip上外网的配置,不过当时更多的是用图形界面来实现的,通用性不强.生产环境,极少有l ...

  9. UML类图简单介绍

    先上一张图: 概述 类图(Class Diagram)是面向对象系统建模中最常用和最重要的图,是定义其它图的基础.类图主要是用来显示系统中的类.接口以及它们之间的静态结构和关系的一种静态模型. 类图组 ...

  10. caching与缓存

    通常,应用程序可以将那些频繁访问的数据,以及那些需要大量处理时间来创建的数据存储在内存中,从而提高性能.例如,如果应用程序使用复杂的逻辑来处理大量数据,然后再将数据作为用户频繁访问的报表返回,避免在用 ...