linux如何切换任务,linux 0.11中简单的任务切换中遇到的问题

linux 0.11中简单的任务切换中遇到的问题

发布时间:2012-03-04 09:49:45来源:红联作者:

最近在学习linux0.11,用的是赵迥博士的一本书,其中有一个模仿Linus 当年做的实验,在屏幕上轮流显示字符A和B,用的是两个任务0和1。并通过定时器进行任务切换,每10ms切换一次。[code]

! boot.s

!

! It then loads the system at 0x10000, using BIOS interrupts. Thereafter

! it disables all interrupts, changes to protected mode, and calls the

BOOTSEG = 0x07c0

SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).

SYSLEN = 17 ! sectors occupied.

entry start

start:

jmpi go,#BOOTSEG

go: mov ax,cs

mov ds,ax

mov ss,ax

mov sp,#0x400 ! arbitrary value >>512

! ok, we've written the message, now

load_system:

mov dx,#0x0000

mov cx,#0x0002

mov ax,#SYSSEG

mov es,ax

xor bx,bx

mov ax,#0x200+SYSLEN

int 0x13

jnc ok_load

die: jmp die

! now we want to move to protected mode ...

ok_load:

cli ! no interrupts allowed !

mov ax, #SYSSEG

mov ds, ax

xor ax, ax

mov es, ax

mov cx, #0x2000

sub si,si

sub di,di

rep

movw

mov ax, #BOOTSEG

mov ds, ax

lidt idt_48 ! load idt with 0,0

lgdt gdt_48 ! load gdt with whatever appropriate

! absolute address 0x00000, in 32-bit protected mode.

mov ax,#0x0001 ! protected mode (PE) bit

lmsw ax ! This is it!

jmpi 0,8 ! jmp offset 0 of segment 8 (cs)

gdt: .word 0,0,0,0 ! dummy

.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)

.word 0x0000 ! base address=0x00000

.word 0x9A00 ! code read/exec

.word 0x00C0 ! granularity=4096, 386

.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)

.word 0x0000 ! base address=0x00000

.word 0x9200 ! data read/write

.word 0x00C0 ! granularity=4096, 386

idt_48: .word 0 ! idt limit=0

.word 0,0 ! idt base=0L

gdt_48: .word 0x7ff ! gdt limit=2048, 256 GDT entries

.word 0x7c00+gdt,0 ! gdt base = 07xxx

.org 510

.word 0xAA55

[/code]和[code]# head.s contains the 32-bit startup code.

# Two L3 task multitasking. The code of tasks are in kernel area,

# just like the Linux. The kernel code is located at 0x10000.

SCRN_SEL = 0x18

TSS0_SEL = 0x20

LDT0_SEL = 0x28

TSS1_SEL = 0X30

LDT1_SEL = 0x38

.text

startup_32:

movl $0x10,%eax

mov %ax,%ds

# mov %ax,%es

lss init_stack,%esp

# setup base fields of descriptors.

call setup_idt

call setup_gdt

movl $0x10,%eax # reload all the segment registers

mov %ax,%ds # after changing gdt.

mov %ax,%es

mov %ax,%fs

mov %ax,%gs

lss init_stack,%esp

# setup up timer 8253 chip.

movb $0x36, %al

movl $0x43, %edx

outb %al, %dx

movl $11930, %eax # timer frequency 100 HZ

movl $0x40, %edx

outb %al, %dx

movb %ah, %al

outb %al, %dx

# setup timer & system call interrupt descriptors.

movl $0x00080000, %eax

movw $timer_interrupt, %ax

movw $0x8E00, %dx

movl $0x08, %ecx # The PC default timer int.

lea idt(,%ecx,8), %esi

movl %eax,(%esi)

movl %edx,4(%esi)

movw $system_interrupt, %ax

movw $0xef00, %dx

movl $0x80, %ecx

lea idt(,%ecx,8), %esi

movl %eax,(%esi)

movl %edx,4(%esi)

# unmask the timer interrupt.

# movl $0x21, %edx

# inb %dx, %al

# andb $0xfe, %al

# outb %al, %dx

# Move to user mode (task 0)

pushfl

andl $0xffffbfff, (%esp)

popfl

movl $TSS0_SEL, %eax

ltr %ax

movl $LDT0_SEL, %eax

lldt %ax

movl $0, current

sti

pushl $0x17

pushl $init_stack

pushfl

pushl $0x0f

pushl $task0

iret

/****************************************/

setup_gdt:

lgdt lgdt_opcode

ret

setup_idt:

lea ignore_int,%edx

movl $0x00080000,%eax

movw %dx,%ax /* selector = 0x0008 = cs */

movw $0x8E00,%dx /* interrupt gate - dpl=0, present */

lea idt,%edi

mov $256,%ecx

rp_sidt:

movl %eax,(%edi)

movl %edx,4(%edi)

addl $8,%edi

dec %ecx

jne rp_sidt

lidt lidt_opcode

ret

# -----------------------------------

write_char:

push %gs

pushl %ebx

# pushl %eax

mov $SCRN_SEL, %ebx

mov %bx, %gs

movl scr_loc, %bx

shl $1, %ebx

movb %al, %gs:(%ebx)

shr $1, %ebx

incl %ebx

cmpl $2000, %ebx

jb 1f

movl $0, %ebx

1: movl %ebx, scr_loc

# popl %eax

popl %ebx

pop %gs

ret

/***********************************************/

/* This is the default interrupt "handler" :-) */

.align 2

ignore_int:

push %ds

pushl %eax

movl $0x10, %eax

mov %ax, %ds

movl $67, %eax /* print 'C' */

call write_char

popl %eax

pop %ds

iret

/* Timer interrupt handler */

.align 2

timer_interrupt:

push %ds

pushl %eax

movl $0x10, %eax

mov %ax, %ds

movb $0x20, %al

outb %al, $0x20

movl $1, %eax

cmpl %eax, current

je 1f

movl %eax, current

ljmp $TSS1_SEL, $0

jmp 2f

1: movl $0, current

ljmp $TSS0_SEL, $0

2: popl %eax

pop %ds

iret

/* system call handler */

.align 2

system_interrupt:

push %ds

pushl %edx

pushl %ecx

pushl %ebx

pushl %eax

movl $0x10, %edx

mov %dx, %ds

call write_char

popl %eax

popl %ebx

popl %ecx

popl %edx

pop %ds

iret

/*********************************************/

current:.long 0

scr_loc:.long 0

.align 2

lidt_opcode:

.word 256*8-1 # idt contains 256 entries

.long idt # This will be rewrite by code.

lgdt_opcode:

.word (end_gdt-gdt)-1 # so does gdt

.long gdt # This will be rewrite by code.

.align 3

idt: .fill 256,8,0 # idt is uninitialized

gdt: .quad 0x0000000000000000 /* NULL descriptor */

.quad 0x00c09a00000007ff /* 8Mb 0x08, base = 0x00000 */

.quad 0x00c09200000007ff /* 8Mb 0x10 */

.quad 0x00c0920b80000002 /* screen 0x18 - for display */

.word 0x0068, tss0, 0xe900, 0x0 # TSS0 descr 0x20

.word 0x0040, ldt0, 0xe200, 0x0 # LDT0 descr 0x28

.word 0x0068, tss1, 0xe900, 0x0 # TSS1 descr 0x30

.word 0x0040, ldt1, 0xe200, 0x0 # LDT1 descr 0x38

end_gdt:

.fill 128,4,0

init_stack: # Will be used as user stack for task0.

.long init_stack

.word 0x10

/*************************************/

.align 3

ldt0: .quad 0x0000000000000000

.quad 0x00c0fa00000003ff # 0x0f, base = 0x00000

.quad 0x00c0f200000003ff # 0x17

tss0: .long 0 /* back link */

.long krn_stk0, 0x10 /* esp0, ss0 */

.long 0, 0, 0, 0, 0 /* esp1, ss1, esp2, ss2, cr3 */

.long 0, 0, 0, 0, 0 /* eip, eflags, eax, ecx, edx */

.long 0, 0, 0, 0, 0 /* ebx esp, ebp, esi, edi */

.long 0, 0, 0, 0, 0, 0 /* es, cs, ss, ds, fs, gs */

.long LDT0_SEL, 0x8000000 /* ldt, trace bitmap */

.fill 128,4,0

krn_stk0:

# .long 0

/************************************/

.align 3

ldt1: .quad 0x0000000000000000

.quad 0x00c0fa00000003ff # 0x0f, base = 0x00000

.quad 0x00c0f200000003ff # 0x17

tss1: .long 0 /* back link */

.long krn_stk1, 0x10 /* esp0, ss0 */

.long 0, 0, 0, 0, 0 /* esp1, ss1, esp2, ss2, cr3 */

.long task1, 0x200 /* eip, eflags */

.long 0, 0, 0, 0 /* eax, ecx, edx, ebx */

.long usr_stk1, 0, 0, 0 /* esp, ebp, esi, edi */

.long 0x17,0x0f,0x17,0x17,0x17,0x17 /* es, cs, ss, ds, fs, gs */

.long LDT1_SEL, 0x8000000 /* ldt, trace bitmap */

.fill 128,4,0

krn_stk1:

/************************************/

task0:

movl $0x17, %eax

movw %ax, %ds

movl $65, %al /* print 'A' */

int $0x80

movl $0xfff, %ecx

1: loop 1b

jmp task0

task1:

movl $0x17, %eax

movw %ax, %ds

movl $66, %al /* print 'B' */

int $0x80

movl $0xfff, %ecx

1: loop 1b

jmp task1

.fill 128,4,0

usr_stk1

[/code]我对其中的定时器中断切换任务困扰了很长一段时间:

定时器中断中使用的是 ljmp $TSS1_SEL,$0 和 ljmp $TSS0_SEL,$0来进行任务切换的。我的理解是,使用ljmp 的执行会妨碍定时器中断的返回,而进入各个任务后执行后,上一次的定时器中断还没结束,就不能响应下一次的中断,这样怎么实现后面的任务切换呢?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值