linux-0.11分析:init文件 main.c的第八个buffer_init(buffer_memory_end)初始化函数 第九篇随笔
2022/8/12 5:23:15
本文主要是介绍linux-0.11分析:init文件 main.c的第八个buffer_init(buffer_memory_end)初始化函数 第九篇随笔,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
8、第八个初始化函数,buffer_init(buffer_memory_end)
参考 [github这个博主的 厉害][ https://github.com/sunym1993/flash-linux0.11-talk ]
这个函数buffer_init
可以看出携带了一个参数buffer_memory_end
,这个参数前面出现过,已经赋值了,
也就是在mian.c
开始的时候
void main(void) { ROOT_DEV = ORIG_ROOT_DEV; drive_info = DRIVE_INFO; memory_end = (1<<20) + (EXT_MEM_K<<10); memory_end &= 0xfffff000; if (memory_end > 16*1024*1024) memory_end = 16*1024*1024; if (memory_end > 12*1024*1024) buffer_memory_end = 4*1024*1024; else if (memory_end > 6*1024*1024) buffer_memory_end = 2*1024*1024; else buffer_memory_end = 1*1024*1024; ......
就是这一段代码把buffer_init
的值设置好了;看看下面这个图吧;根据内存大小不一样位置也不一样;总之它是指向缓存区的主要需要用到的内存的开始
之前通过第一个初始化函数mem_init
把用mem_map
内存管理了起来;
include文件 -> linux文件 -> fs.h
buffer_head
这个结构体
#define NR_HASH 307 #define BLOCK_SIZE 1024 struct buffer_head { char * b_data; /* pointer to data block (1024 bytes) */ unsigned long b_blocknr; /* block number */ unsigned short b_dev; /* device (0 = free) */ unsigned char b_uptodate; unsigned char b_dirt; /* 0-clean,1-dirty */ unsigned char b_count; /* users using this block */ unsigned char b_lock; /* 0 - ok, 1 -locked */ struct task_struct * b_wait; //之前用到那个task[64]数组的那个结构体 struct buffer_head * b_prev; struct buffer_head * b_next; struct buffer_head * b_prev_free; struct buffer_head * b_next_free; };
看看这个初始化函数buffer_init
的代码吧:
fs文件 -> buffer.c
#define BLOCK_SIZE 1024 extern int end; int NR_BUFFERS = 0; static struct buffer_head * free_list; struct buffer_head * hash_table[NR_HASH]; void buffer_init(long buffer_end) { struct buffer_head * h = start_buffer; void * b; int i; if (buffer_end == 1<<20) // 1<<20 为1MB b = (void *) (640*1024); else b = (void *) buffer_end; while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) { //BLOCK_SIZE=1024 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; h->b_prev = NULL; h->b_data = (char *) b; h->b_prev_free = h-1; h->b_next_free = h+1; h++; NR_BUFFERS++; //NR_BUFFERS = 0 if (b == (void *) 0x100000) b = (void *) 0xA0000; } h--; free_list = start_buffer; free_list->b_prev_free = h; h->b_next_free = free_list; for (i=0;i<NR_HASH;i++) //NR_HASH=307 hash_table[i]=NULL; }
先看看这一个宏定义
extern int end; struct buffer_head * start_buffer = (struct buffer_head *) &end;
这个end
是一个外部变量,
这个外部变量 end 并不是操作系统代码写就的,而是由链接器 ld 在链接整个程序时设置的一个外部变量,帮我们计算好了整个内核代码的末尾地址。
再看start_buffer就是取的end
的地址为buffer_head
这个结构体定义的start_buffer
所以start_buffer
是这个这个缓冲区的开始的位置
第一部分:
void * b; if (buffer_end == 1<<20) // 1<<20 为1MB buffer_end = buffr_memory_end b = (void *) (640*1024); else b = (void *) buffer_end;
判断了传入的主要内存开始的位置是否等于1MB;如果等于b
的值就置为640*1024这个位置;否则就是本身
第二部分:
struct buffer_head * h = start_buffer; void * b; int i; while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) { //BLOCK_SIZE=1024 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; h->b_prev = NULL; h->b_data = (char *) b; h->b_prev_free = h-1; h->b_next_free = h+1; h++; NR_BUFFERS++; //NR_BUFFERS = 0 if (b == (void *) 0x100000) b = (void *) 0xA0000; }
可以这是在把缓冲区分块,
很明显,b是缓冲区尾部,h为缓冲区的头部,
从尾部开始向下进行分块,一块大小为1024也就是一页,每分一块前面的缓冲区头就加一个,
并且它里面的h->b_data
就指向刚刚产生着块缓冲区,
h->b_prev_free = h-1
指向上一个头; h->b_next_free = h+1
指向下一个头
看看下面这个图吧
第三部分:
h--; free_list = start_buffer; free_list->b_prev_free = h; h->b_next_free = free_list;
这就在实现双向链表,把最后h
的下一个(next)指向第一个,把第一个的上一个(prve)指向最后一个
老规矩看图
第四部分:
struct buffer_head * hash_table[NR_HASH]; ...... for (i=0;i<NR_HASH;i++) hash_table[i]=NULL; //NR_HASH=307
这里可以看出就是把buffer_head
的结构体数组hash_table[307]
大小为307的置为空
这是数组的作用是干啥?
引用:[github的博主所讲的内容;多多支持][https://mp.weixin.qq.com/s/X8BSbf1qShS11_fzfyOhTg]
其实今天的这个代码在 buffer.c 中,而 buffer.c 是在 fs 包下的,也就是文件系统包下的。所以它今后是为文件系统而服务,具体是内核程序如果需要访问块设备中的数据,就都需要经过缓冲区来间接地操作。
也就是说,读取块设备的数据(硬盘中的数据),需要先读到缓冲区中,如果缓冲区已有了,就不用从块设备读取了,直接取走。
那怎么知道缓冲区已经有了要读取的块设备中的数据呢?从双向链表从头遍历当然可以,但是这效率可太低了。所以需要一个 hashmap 的结构方便快速查找,这就是 hash_table 这个数组的作用。
这篇关于linux-0.11分析:init文件 main.c的第八个buffer_init(buffer_memory_end)初始化函数 第九篇随笔的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南
- 2024-08-21【Linux】分区向左扩容的方法