ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux-0.11分析:init文件 main.c的第八个buffer_init(buffer_memory_end)初始化函数 第九篇随笔

2022-08-11 12:31:55  阅读:284  来源: 互联网

标签:1024 head end struct buffer free init memory


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 这个数组的作用。

标签:1024,head,end,struct,buffer,free,init,memory
来源: https://www.cnblogs.com/shuisanya/p/16575620.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有