如何创建自己公司网站,wordpress企业主题制作视频教程,开发网站私活,wordpress 数字指纹回忆我们需要做的事情#xff1a; 为了支持 shell 程序的执行#xff0c;我们需要提供#xff1a; 1.缺页中断(不理解为什么要这个东西#xff0c;只是闪客说需要#xff0c;后边再说) 2.硬盘驱动、文件系统 (shell程序一开始是存放在磁盘里的#xff0c;所以需要这两个东…回忆我们需要做的事情 为了支持 shell 程序的执行我们需要提供 1.缺页中断(不理解为什么要这个东西只是闪客说需要后边再说) 2.硬盘驱动、文件系统 (shell程序一开始是存放在磁盘里的所以需要这两个东西) 3.fork,execve, wait 这三个系统调用也可以说是 进程调度 (否则无法 halt shell 程序并且启动另外的程序) 4.键盘驱动、VGA/console/uart 驱动、中断处理 (支持键盘输入和屏幕显示) 5.内存管理 (shell 启动其它进程时不能共用内存而是切换其它进程的页表) — 完成内核内存管理 6.为了写代码方便我们需要从 MBR 进入到 main 函数这也是从 汇编 切换到 C 语言 — 已经完成 7.应用程序申请内存的接口
现在已经进入 main 函数了在内核中实现了初步的内核进程管理 (kfree kalloc)
读闪客文章 “你的键盘是什么时候生效的”
https://mp.weixin.qq.com/s?__bizMzk0MjE3NDE0Ngmid2247500119idx1snf46331f70677aba168243040a96be1c0chksmc2c5bbfaf5b232ec6ed2187d0a8ae3a6001ab5997b9ee838f3b32aa892d9a41157473e90195fscene178cur_album_id2123743679373688834#rd
那我们今天就来刨根问底一下到底过了多久之后按下键盘才有效果呢
当然首先你得知道按下键盘后会触发中断CPU 收到你的键盘中断后根据中断号寻找由操作系统写好的键盘中断处理程序。
中断的原理和过程不了解的可以看我的文章认认真真的聊聊中断
这个中断处理程序会把你的键盘码放入一个队列中由相应的用户程序或内核程序读取并显示在控制台或者其他用途这就代表你的键盘生效了。
不过放宽心我们不展开讲这个中断处理程序以及用户程序读取键盘码后的处理细节我们把关注点放在究竟是“什么时候”按下键盘才会有这个效果。
我们以 Linux 0.11 源码为例发现进入内核的 main 函数后不久有这样一行代码。
void main(void) {...trap_init();...
}看到这个方法的全部代码后你可能会会心一笑也可能一脸懵逼。
void trap_init(void) {int i;set_trap_gate(0,divide_error);set_trap_gate(1,debug);set_trap_gate(2,nmi);set_system_gate(3,int3); /* int3-5 can be called from all */set_system_gate(4,overflow);set_system_gate(5,bounds);set_trap_gate(6,invalid_op);set_trap_gate(7,device_not_available);set_trap_gate(8,double_fault);set_trap_gate(9,coprocessor_segment_overrun);set_trap_gate(10,invalid_TSS);set_trap_gate(11,segment_not_present);set_trap_gate(12,stack_segment);set_trap_gate(13,general_protection);set_trap_gate(14,page_fault);set_trap_gate(15,reserved);set_trap_gate(16,coprocessor_error);for (i17;i48;i)set_trap_gate(i,reserved);set_trap_gate(45,irq13);set_trap_gate(39,parallel_interrupt);
}这啥玩意这么多 set_xxx_gate。
有密集恐惧症的话绝对看不下去这个代码所以我就给他简化一下。
把相同功能的去掉。
void trap_init(void) {int i;// set 了一堆 trap_gateset_trap_gate(0, divide_error);... // 又 set 了一堆 system_gateset_system_gate(45, bounds);...// 又又批量 set 了一堆 trap_gatefor (i17;i48;i)set_trap_gate(i, reserved);...
}这就简单多了我们一块一块看。
首先我们看 set_trap_gate 和 set_system_gate 这俩货发现了这么几个宏定义。
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ (movw %%dx,%%ax\n\t \movw %0,%%dx\n\t \movl %%eax,%1\n\t \movl %%edx,%2 \: \: i ((short) (0x8000(dpl13)(type8))), \o (*((char *) (gate_addr))), \o (*(4(char *) (gate_addr))), \d ((char *) (addr)),a (0x00080000))#define set_trap_gate(n,addr) \_set_gate(idt[n],15,0,addr)#define set_system_gate(n,addr) \_set_gate(idt[n],15,3,addr)不过这俩都是最终指向了相同的另一个宏定义 _set_gate说明是有共性的。
啥共性呢我直接说吧那段你完全看不懂的代码是将汇编语言嵌入到 c 语言了这种内联汇编的格式非常恶心所以我也不想搞懂它最终的效果就是在中断描述符表中插入了一个中断描述符。
中断描述符表还记得吧英文叫 idt。 这段代码就是往这个 idt 表里一项一项地写东西其对应的中断号就是第一个参数中断处理程序就是第二个参数。
产生的效果就是之后如果来一个中断后CPU 根据其中断号就可以到这个中断描述符表 idt 中找到对应的中断处理程序了。
比如这个。
set_trap_gate(0,divide_error);就是设置 0 号中断对应的中断处理程序是 divide_error。
等 CPU 执行了一条除零指令的时候会从硬件层面发起一个 0 号异常中断然后执行由我们操作系统定义的 divide_error 也就是除法异常处理程序执行完之后再返回。
再比如这个。
set_system_gate(5,overflow);就是设置 5 号中断对应的中断处理程序是 overflow是边界出错中断。
TIPS这个 trap 与 system 的区别仅仅在于设置的中断描述符的特权级不同前者是 0内核态后者是 3用户态这块展开将会是非常严谨的、绕口的、复杂的特权级相关的知识不明白的话先不用管就理解为都是设置一个中断号和中断处理程序的对应关系就好了。
再往后看批量操作这里。
void trap_init(void) {...for (i17;i48;i)set_trap_gate(i,reserved);...
}17 到 48 号中断都批量设置为了 reserved 函数这是暂时的后面各个硬件初始化时要重新设置好这些中断把暂时的这个给覆盖掉此时你留个印象。
所以整段代码执行下来内存中那个 idt 的位置会变成如下的样子。 好了我们看到了设置中断号与中断处理程序对应的地方那这行代码过去后键盘好使了么
NO
键盘产生的中断的中断号是 0x21此时这个中断号还仅仅对应着一个临时的中断处理程序 reserved我们接着往后看。
在这行代码往后几行还有这么一行代码。
void main(void) {...trap_init();...tty_init();...
}void tty_init(void) {rs_init();con_init();
}void con_init(void) {...set_trap_gate(0x21,keyboard_interrupt);...
}我省略了大量的代码只保留了我们关心的。
注意到 trap_init 后有个 tty_init最后根据调用链会调用到一行添加 0x21 号中断处理程序的代码就是刚刚熟悉的 set_trap_gate。
而后面的 keyboard_interrupt 根据名字也可以猜出就是键盘的中断处理程序嘛
好了那我们终于找到大案了就是从这一行代码开始我们的键盘生效了
没错不过还有点小问题不过不重要就是我们现在的中断处于禁用状态不论是键盘中断还是其他中断通通都不好使。
而 main 方法继续往下读还有一行这个东西。
void main(void) {...trap_init();...tty_init();...sti();...
}sti 最终会对应一个同名的汇编指令 sti表示允许中断。所以这行代码之后键盘才真正开始生效
动画酷不酷好啦今天的文章就到这里了中断的原理和细节就看我之前的文章认认真真的聊聊中断。
键盘处理的具体流程可以跟着我今天的代码深入进去看看哟Linux 0.11 里还是很简单的。
TODO 闪客省略了键盘处理的具体流程以后有空我们也可以看一看
读完闪客文章 “你的键盘是什么时候生效的”