linux-0.11分析:init文件 main.c的第9个hd_init()、第10个floppy_init()和第11个sit()初始化函数 第十篇随笔
9、第九个初始化函数,hd_init()
参考 [github这个博主的 厉害][ https://github.com/sunym1993/flash-linux0.11-talk ]
先看看这个初始化函数hd_init()
:
kernel文件 -> blk_drv文件 -> hd.c
#define MAJOR_NR 3
void hd_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_intr_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1);
}
可以简单看出就这四行代码;
第一部分:
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blk_dev
是blk_dev_struct
的结构体实例,
从下面的可以看出 #ifdef MAJOR_NR
可以看出,当MAJOR_NR
去不同值的时候对应着不同的值
这里的MAJOR_NR=3
所有 #define DEVICE_REQUEST do_hd_request
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
这句话也就是把第3个的request_fn属性赋值为do_hd_request
;注意:blk_dev
这个数值总的长度为7
do_hd_request
作用
引用:[github的博主所讲的内容;多多支持][https://mp.weixin.qq.com/s/X8BSbf1qShS11_fzfyOhTg]
那么每个块设备执行读写请求都有自己的函数实现,在上层看来都是一个统一函数 request_fn 即可,具体实现各有不同,对于硬盘来说,这个实现就是 do_hd_request 函数。
是不是有点像接口?这其实就是多态思想在 C 语言的体现嘛~ 用 Java 程序员熟悉的话就是,父类引用
request_fn
指向子类对象do_hd_request
的感觉咯。
kernel文件 -> blk_drv文件 -> blk.h
#define NR_BLK_DEV 7
struct blk_dev_struct {
void (*request_fn)(void);
struct request * current_request;
};
extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
#ifdef MAJOR_NR
#if (MAJOR_NR == 1)
/* ram disk */
#define DEVICE_NAME "ramdisk"
#define DEVICE_REQUEST do_rd_request
#define DEVICE_NR(device) ((device) & 7)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif (MAJOR_NR == 2)
/* floppy */
#define DEVICE_NAME "floppy"
#define DEVICE_INTR do_floppy
#define DEVICE_REQUEST do_fd_request
#define DEVICE_NR(device) ((device) & 3)
#define DEVICE_ON(device) floppy_on(DEVICE_NR(device))
#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
#elif (MAJOR_NR == 3)
/* harddisk */
#define DEVICE_NAME "harddisk"
#define DEVICE_INTR do_hd
#define DEVICE_REQUEST do_hd_request
#define DEVICE_NR(device) (MINOR(device)/5)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif
/* unknown blk device */
#error "unknown blk device"
#endif
第二部分:
set_intr_gate(0x2E,&hd_interrupt);
这个就已经很熟悉,就是设置了一个0x2E
的中断,中断函数为:hd_interrupt
到目前为止,中断已经设置了不少了,我们现在看看所设置好的中断有哪些。
中断号 | 中断处理函数 |
---|---|
0 ~ 0x10 | trap_init 里设置的一堆 |
0x20 | timer_interrupt |
0x21 | keyboard_interrupt |
0x2E | hd_interrupt |
0x80 | system_call |
第三部分:
outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1);
这又是读盘操作了,就是往几个 IO 端口上读写,其作用是允许硬盘控制器发送中断请求信号
10、第十个初始化函数,floppy_init()
先来看看这个函数吧
kernel文件 -> blk_drv文件 -> floppy.c
#define MAJOR_NR 2
void floppy_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_trap_gate(0x26,&floppy_interrupt);
outb(inb_p(0x21)&~0x40,0x21);
}
这个其实就和第八个初始化函数参不多,设置第2个blk_dev
数据;
然后有开启了一个中断0x26中断,中断处理函数为floppy_interrupt
到目前为止,中断已经设置了不少了,我们现在看看所设置好的中断有哪些。
中断号 | 中断处理函数 |
---|---|
0 ~ 0x10 | trap_init 里设置的一堆 |
0x20 | timer_interrupt |
0x21 | keyboard_interrupt |
0x26 | floppy_interrupt |
0x2E | hd_interrupt |
0x80 | system_call |
然后又是读盘操作
这里对这个初始化函数就不过多赘述了,软盘的操作现在基本上被淘汰了
11、第十一个函数,sit()
看看这函数吧
include文件 -> asm文件 -> system.h
#define sti() __asm__ ("sti"::)
它的本质就是一段内嵌汇编代码,sti的一个指令,表示开启中断.
其本质上是将 eflags 寄存器里的中断允许标志位 IF 位置 1。