linux0.00,linux-0.00源代码

linux-0.00很简单,两个进程task0,task1,task0打印A,task1打印B,在时钟中断中调度进程运行。

据说后来linus丢失了这个最初的版本,这里是赵炯博士写的linux-0.00版本。

我把源代码上传到了csdn的资源里面,在这里下载,可以用bochs模拟,赶紧试试吧

0818b9ca8b590ca3270a3433284dd417.png

简单说一下,就两个文件,boot.s和head.s。

head.s被编译成system模块

boot.s编译出的MBR用于将编译出的system模块从软盘中读到内存0x10000处,然后跳到0x10000执行。

head.s编译出的system模块设置好task0的tss0和ldt0,以及task1的tss1和ldt1后,初始化idt和gdt,最后在idt中填入两个中断门描述符:时钟中断timer_interrupt和系统调用中断system_interrupt。

然后构造出task0的人工堆栈环境,使用iret指令跳到task0出执行。

多任务实现的关键代码在时钟中断里,如下

/* Timer interrupt handler */

.align 2

timer_interrupt:

push %ds

pushl %edx

pushl %ecx

pushl %ebx

pushl %eax

movl $0x10, %eax #数据段描述符

mov %ax, %ds

movb $0x20, %al #向8253发送EOI

outb %al, $0x20

movl $1, %eax

cmpl %eax, current #current == x 表示当前运行的是taskx (task0/task1)

je 1f

movl %eax, current #从task0切到task1

ljmp $TSS1_SEL, $0 #执行这句完之后,就会跳到task1代码处执行,task0的tss0的eip处将被填入下一句代码"jmp 2f"的地址,等到切换到task0的时候,从jmp 2f处开始执行

jmp 2f

1: movl $0, current #从task1切到task0

ljmp $TSS0_SEL, $0 #同上,task1的tss1中的eip将会存入"popl %eax"的地址

2: popl %eax

popl %ebx

popl %ecx

popl %edx

pop %ds

iret

注意跳转的这两句ljmp。让我们来模拟一下:

0. 首先执行的是task0。

1. task0运行过程中发生时钟中断,根据逻辑

ljmp $TSS1_SEL, $0跳入到task1的代码中去,此时会把下一条语句即jmp 2f的地址存入到task0的tss中的eip条目中。

2. 从task1的tss1中恢复各个寄存器,使task1运行。

3. task1运行过程中发生时钟中断,根据逻辑

ljmp $TSS0_SEL, $0跳到task0的代码中去,此时会把下一条语句即popl %eax存入到task1的tss中的eip条目中。

4. cpu根据task0的tss中的eip条目恢复task0,即task0从jmp 2f往下执行,最后执行iret返回到task0的代码中。

5. task0运行过程中再次发生时钟中断,这时候恢复task1的寄存器上下文,从popl %eax出继续往下执行。

6  ....

这样就形成了task0和task1的多任务运行,对于task0来说,它完全感觉不到task1的存在,每次它的寄存器上下文都能被完整的恢复,对于task1来说也一样。

时钟中断这个过程是可以重入的,可以把这个过程理解成task0和task1共用(代码共用)的一个私有(执行流私有)过程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值