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。

posted @ 2022-08-12 13:01  水三丫  阅读(131)  评论(0编辑  收藏  举报