好的,OK,心情不好就输出,操作系统真是解忧啊~~~~
buffer_init(buffer_memory_end)
前面我们已经把主内存区的初始化大表给建立起来了,现在就来看缓冲区的管理。
extern int end;
struct buffer_head * start_buffer = (struct buffer_head *) &end;
void buffer_init(long buffer_end) {
struct buffer_head * h = start_buffer;
void * b = (void *) buffer_end;
while ( (b -= 1024) >= ((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;
h->b_prev = NULL;
h->b_data = (char *) b;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
}
h--;
free_list = start_buffer;
free_list->b_prev_free = h;
h->b_next_free = free_list;
for (int i=0;i<307;i++)
hash_table[i]=NULL;
}
外部变量end
end赋值给了我们的缓冲区的开始变量start_buffer。
由链接器ld在链接整个程序时设置的一个外部变量,帮我们计算好了整个内核代码的末尾地址。
void buffer_init(long buffer_end) {
struct buffer_head * h = start_buffer;
void * b = (void *) buffer_end;
while ( (b -= 1024) >= ((void *) (h+1)) ) {
...
h->b_data = (char *) b;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
}
...
}
这里有一个buffer_head的结构h,代表缓冲头
这里有一个b,代表缓冲块,指针值是buffer_end,也就是缓冲区结尾。
缓冲区结尾的b 每次循环-1024,也就是一页的值,缓冲区结尾的h每次循环+1,直到碰到一块为止。
这个h,有三个东西,b_data指向b , b_prev_free指向前一个,b_next_free指向后一个,可以看出这是一个管理缓冲块的双向链表。
void buffer_init(long buffer_end) {
...
free_list = start_buffer;
free_list->b_prev_free = h;
h->b_next_free = free_list;
...
}
缓冲头是具体缓冲块的管理结构,free_list开头的双向链表是缓冲头的管理结构
void buffer_init(long buffer_end) {
...
for (i=0;i<307;i++)
hash_table[i]=NULL;
}
这里有一个307的hash_table数组,这个是用来看块设备读取时,要读取的数据是否已经在内存缓冲区存在了。如果存在直接读内存缓冲区就可以了。
hd_init()
终于来到了硬盘初始化。
//struct blk_dev_struct {
// void (*request_fn)(void);
// struct request * current_request;
//};
//extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
void hd_init(void) {
blk_dev[3].request_fn = do_hd_request;
set_intr_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1);
}
对于硬件设备的初始化大体都是1.往某些IO端口上读写一些文件,表示开启它;2.向中断向量表中添加一个中断,使得CPU能够响应这个硬件设备的动作。3.初始化一些数据结构来管理。
第一行代码:把blk_dev数组索引3的位置的块设备管理结构blk_dev_struct的request_fn赋值为do_hd_request。
struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
{ NULL, NULL }, /* no_dev */
{ NULL, NULL }, /* dev mem */
{ NULL, NULL }, /* dev fd */
{ NULL, NULL }, /* dev hd */
{ NULL, NULL }, /* dev ttyx */
{ NULL, NULL }, /* dev tty */
{ NULL, NULL } /* dev lp */
};
因为有很多块设备,用一个blk_dev数组来管理,每一个索引表示一个块设备。
索引为3是给硬盘这个块设备留的位置。
每个块设备执行读写请求都有自己的函数实现,在上层看来都是一个同一个的函数request_fn,但是具体实现各有不同,就相当于多态,这个硬盘的读写函数就是do_hd_request;
第二行代码
set_intr_gate(0x2E,&hd_interrupt);
这里是设置一个硬盘中断,这个已经完全不陌生了,我们之前在中断初始化的时候设置了一些中断,然后键盘中断,时钟中断和系统调用中断,加上现在的硬盘中断。
最后两行代码就是网几个IO端口上读写,作用是允许硬盘控制器发送中断请求信号。
好的,OK,今天就说到这里吧,有问题欢迎留言讨论!!