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。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)