经过了一天的努力,在刚才,总算出现了上面激动人心的画面了:
真的很高兴,趁着还热乎,赶快记下来:
综述
第六章是 进程
。不过现在这一章的 进程
其实是有点取巧的,它是事先将一个进程需要的寄存器,栈,LDT,代码等准备好,弄成一个进程表,一切都准备完了之后,将 esp
指向进程表的顶部,然后一个一个地 pop
,然后一个跳转,我们的第一个进程就开始运行了。
由于涉及到特权级的转换,所以需要 tss
来记录每个特权级的 ss
和 esp
,以便当低特权级到高特权级的切换时,堆栈也能够切换。
由于现在我还没有实现中断,所以,这个进程是一直都在运行的,没有被打断的。不过这种情况将会改变,不过得明天吧。
代码解读
一开始的这些代码没有什么难的,主要提一点:
在 /kernel/main.c
的 line 27 和 line 29 这两行代码中,有一个我之前一直无法理解的,就是 >> 3
。现解释如下:
每个描述符的大小是 8 字节,
>> 3
就相当于除以8
,这样就能够得到相应的描述符在gdt数组
的具体位置了。
犯过的错误以及总结
typedef
之后忘记了一个最重要的;
. 导致出现了很多匪夷所思的错误,例如提示说#define EXTERN extern
这一句有错等等。每增加一个新的函数就要在
inlcude/proto.h
里面添加相应的声明。有关字符串的函数声明在
include/string.h
里面用汇编实现的函数如果要被其他文件调用,**千万记得要用
global
**。不然肯定是会报undefined reference to xxx
的!一开始出现了
#GP
的错误,提示说在cs:0x8 eip:0x3059E
这里出现了错误,反汇编了一下,发现这个位置对应的代码是:lldt [esp + P_LDT_SEL]
根据
p_proc->regs.eflags = 0x1202
,找到了restart()
的位置:0x30598
.不过后来发现了,又是一个粗心导致的错误,我忘记填充 GDT 中的 LDT 的描述符了。不过,发生
#GP
的结果跟我查文档的结果是一样的。
收获
又是花了很多时间在 Debugging
上,不过这一次总算有所收获。
bochs
的sreg
指令能够查看LDTR
。print-stack
后面加个数字能够控制输出的栈的长度
最后,如果你们也想要体验一下 Debug
的话,我把我的 Debug
的过程公开出来:
b 0x7d12 (找到 loader 之后的跳转)
c
b 0x9027e (跳入保护模式)
c
b 0x9039b (跳入内核)
c
b 0x310c9 (restart())
声明,上面的地址只对于我的代码有效,你自己实现的代码与我的可能有出入
下面是原书代码的 Debug
过程:
b 0x7d0a (找到 loader 之后的跳转)
c
b 0x9027f (跳入保护模式)
c
b 0x90393 (跳入内核)
c
b 0x3071c (这一句是根据 kernel/main.c 中很明显的 0x1202 找到的,下面几行就是 restart() 了)
大概就是这些了。明天继续~
EOF
Author: simowce
Permalink: https://blog.simowce.com/chapter-6-single-process/
本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。