首先我们的中断处理函数过于简单,起码应该保持相关的寄存器,所以System_call.S修改如下:
.globl timer_interrupt timer_interrupt: push %ds pushl %edx pushl %ecx pushl %ebx pushl %eax movl $0x10, %eax mov %ax, %ds incl jiffies movb $0x20,%al outb %al,$0x20 call do_timer popl %eax popl %ebx popl %ecx popl %edx pop %ds iret
struct task_struct { long state; long pid,father; struct desc_struct ldt[3]; /* tss for this task */ struct tss_struct tss; };
#define INIT_TASK \ { 0,0,0,\ { \ {0,0}, \ /* ldt */ {0x9f,0xc0fa00}, \ {0x9f,0xc0f200}, \ }, \ /*tss*/ {\ }, \ } #define PAGE_SIZE 4096 union task_union { struct task_struct task; char stack[PAGE_SIZE]; }; static union task_union init_task = {INIT_TASK,}; static union task_union task1 = {INIT_TASK,};
struct stack_struct{ char stack[256]; int top; }; struct stack_struct stack0; struct stack_struct stack1;
void main(void) { disp_str("How old are you?\n"); set_intr_gate(32,&timer_interrupt); _set_gdt_desc(&gdt[1],0x0000,0x7ff,DA_CR+DA_32+DA_LIMIT_4K); //堆栈段 0x10 _set_gdt_desc(&gdt[2],0x0000,0x7ff,DA_DRW+DA_32+DA_LIMIT_4K); //视频段 0x18 _set_gdt_desc(&gdt[3],0xb8000,0x2,DA_DRW+DA_32+DA_DPL3+DA_LIMIT_4K); //init_task的LDT 0x28 _set_gdt_desc(&gdt[5],&init_task.task.ldt[0],0x40,DA_LDT); //task1的LDT 0x38 _set_gdt_desc(&gdt[7],&task1.task.ldt[0],0x40,DA_LDT); //填充init_task的TSS init_task.task.tss.backlink = 0; init_task.task.tss.esp0=PAGE_SIZE+(long)&init_task; init_task.task.tss.ss0=0x10; init_task.task.tss.eip=&testA; init_task.task.tss.esp = &stack0.top; init_task.task.tss.flags=0x200; init_task.task.tss.es=0x17; init_task.task.tss.cs=0xf; init_task.task.tss.ss=0x17; init_task.task.tss.ds=0x17; init_task.task.tss.fs=0x17; init_task.task.tss.gs=0x18; init_task.task.tss.ldt=0x28; init_task.task.tss.trap=0x8000; init_task.task.tss.iobase=0x0; //init_task的TSS 0x20 _set_gdt_desc(&gdt[4],&init_task.task.tss,0x68,DA_386TSS+DA_DPL3); //填充task1的TSS task1.task.tss.backlink = 0; task1.task.tss.esp0=PAGE_SIZE+(long)&task1;//&stack1_krn_ptr; task1.task.tss.ss0=0x10; task1.task.tss.eip=&testC; task1.task.tss.esp = &stack1.top; task1.task.tss.flags=0x200; task1.task.tss.es=0x17; task1.task.tss.cs=0xf; task1.task.tss.ss=0x17; task1.task.tss.ds=0x17; task1.task.tss.fs=0x17; task1.task.tss.gs=0x18; task1.task.tss.ldt=0x38; task1.task.tss.trap=0x8000; task1.task.tss.iobase=0x0; //task1的TSS 0x30 _set_gdt_desc(&gdt[6],&task1.task.tss,0x68,DA_386TSS+DA_DPL3); //task[1] = &(task1.task); ltr();//加载tss lldt();//加载ldt sti();//开中断 move_to_user_mode(); while(1); }任务有了就该任务切换了,这个动作我们在do_timer函数中做
int current_task=0; //task0的tss选择子为0x20;task1的tss选择子为0x30 #define enter_task0() __asm__ ("ljmp $0x20, $0\n\t" :::) #define enter_task1() __asm__ ("ljmp $0x30, $0\n\t" :::) void do_timer(void) { if(current_task) { current_task = 0; enter_task0(); } else { current_task = 1; enter_task1(); } disp_str("T"); }
#define DA_CR 0x9A #define DA_LIMIT_4K 0x8000 #define DA_386TSS 0x89 #define DA_LDT 0x82 #define set_registers() \ __asm__ ("movl $0x17,%%eax\n\t" \ "movw %%ax,%%ds\n\t" \ "movw %%ax,%%es\n\t" \ "movw %%ax,%%fs\n\t" \ "movw $0x18,%%ax\n\t" \ "movw %%ax,%%gs" \ :::"ax") #define move_to_user_mode() \ __asm__ ("movl %%esp,%%eax\n\t" \ "pushl $0x17\n\t" \ "pushl %%eax\n\t" \ "pushfl\n\t"\ "pushl $0xf\n\t" \ "pushl $testA\n\t" \ "iret\n" \ :::"ax") #define lldt() \ __asm__ ("movw $0x28,%%ax\n\t" \ "lldt %%ax\n\t" \ :::"ax") #define ltr() \ __asm__ ("movw $0x20,%%ax\n\t" \ "ltr %%ax\n\t" \ :::"ax")中循环打印一个‘C’
void testC(void) { while(1){ disp_str("C"); delay(2); } }
执行效果如下图,A是任务0打印的,C是任务1打印的,T是do_timer中打印的
#include <linux/head.h> #include <asm/system.h> #include <asm/io.h> extern void divide_error(void); void disp_str(char *info); #define DA_C 0x98 #define DA_32 0x4000 #define DA_DPL3 0x60 #define DA_DPL0 0x00 #define DA_DRWA 0x93 #define DA_DRW 0x92 #define SA_RPL3 3 #define DA_CR 0x9A #define DA_LIMIT_4K 0x8000 #define DA_386TSS 0x89 #define DA_LDT 0x82 #define set_registers() \ __asm__ ("movl $0x17,%%eax\n\t" \ "movw %%ax,%%ds\n\t" \ "movw %%ax,%%es\n\t" \ "movw %%ax,%%fs\n\t" \ "movw $0x18,%%ax\n\t" \ "movw %%ax,%%gs" \ :::"ax") #define move_to_user_mode() \ __asm__ ("movl %%esp,%%eax\n\t" \ "pushl $0x17\n\t" \ "pushl %%eax\n\t" \ "pushfl\n\t"\ "pushl $0xf\n\t" \ "pushl $testA\n\t" \ "iret\n" \ :::"ax") #define lldt() \ __asm__ ("movw $0x28,%%ax\n\t" \ "lldt %%ax\n\t" \ :::"ax") #define ltr() \ __asm__ ("movw $0x20,%%ax\n\t" \ "ltr %%ax\n\t" \ :::"ax") void delay(int time) { int i, j, k; for (k = 0; k < time; k++) { for (i = 0; i < 10; i++) { for (j = 0; j < 10000; j++) {} } } } void testA(void) { set_registers(); while(1){ disp_str("A"); delay(2); } } void testC(void) { while(1){ disp_str("C"); delay(2); } } typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; typedef struct Descriptor /* ???8 ??a?-?è??*/ { u16 limit_low; /* Limit */ u16 base_low; /* Base */ u8 base_mid; /* Base */ u8 attr1; /* P(1) DPL(2) DT(1) TYPE(4) */ u8 limit_high_attr2; /* G(1) D(1) 0(1) AVL(1) LimitHigh(4) */ u8 base_high; /* Base */ }DESCRIPTOR; void _set_gdt_desc(struct desc_struct *descriptor_addr,u32 base,u32 limit,u16 attr) { DESCRIPTOR *descriptor = (DESCRIPTOR *)descriptor_addr; descriptor->limit_low = limit & 0x0FFFF; descriptor->base_low = base & 0x0FFFF; descriptor->base_mid = (base >> 16) & 0x0FF; descriptor->attr1 = attr & 0xFF; descriptor->limit_high_attr2= ((limit>>16) & 0x0F) | (attr>>8) & 0xF0; descriptor->base_high = (base >> 24) & 0x0FF; } typedef struct tss_struct { u32 backlink; u32 esp0; /* stack pointer to use during interrupt */ u32 ss0; /* " segment " " " " */ u32 esp1; u32 ss1; u32 esp2; u32 ss2; u32 cr3; u32 eip; u32 flags; u32 eax; u32 ecx; u32 edx; u32 ebx; u32 esp; u32 ebp; u32 esi; u32 edi; u32 es; u32 cs; u32 ss; u32 ds; u32 fs; u32 gs; u32 ldt; u16 trap; u16 iobase; /* I/O位图基址大于或等于TSS段界限,就表示没有I/O许可位图 */ }TSS; extern void timer_interrupt(void); long volatile jiffies=0; int current_task=0; //task0的tss选择子为0x20;task1的tss选择子为0x30 #define enter_task0() __asm__ ("ljmp $0x20, $0\n\t" :::) #define enter_task1() __asm__ ("ljmp $0x30, $0\n\t" :::) void do_timer(void) { if(current_task) { current_task = 0; enter_task0(); } else { current_task = 1; enter_task1(); } disp_str("T"); } struct task_struct { long state; long pid,father; struct desc_struct ldt[3]; /* tss for this task */ struct tss_struct tss; }; #define INIT_TASK \ { 0,0,0,\ { \ {0,0}, \ /* ldt */ {0x9f,0xc0fa00}, \ {0x9f,0xc0f200}, \ }, \ /*tss*/ {\ }, \ } #define PAGE_SIZE 4096 #define NR_TASKS 64 union task_union { struct task_struct task; char stack[PAGE_SIZE]; }; static union task_union init_task = {INIT_TASK,}; //struct task_struct *current = &(init_task.task); //struct task_struct * task[NR_TASKS] = {&(init_task.task), }; static union task_union task1 = {INIT_TASK,}; struct stack_struct{ char stack[256]; int top; }; struct stack_struct stack0; struct stack_struct stack1; void main(void) { disp_str("How old are you?\n"); set_intr_gate(32,&timer_interrupt); _set_gdt_desc(&gdt[1],0x0000,0x7ff,DA_CR+DA_32+DA_LIMIT_4K); //堆栈段 0x10 _set_gdt_desc(&gdt[2],0x0000,0x7ff,DA_DRW+DA_32+DA_LIMIT_4K); //视频段 0x18 _set_gdt_desc(&gdt[3],0xb8000,0x2,DA_DRW+DA_32+DA_DPL3+DA_LIMIT_4K); //init_task的LDT 0x28 _set_gdt_desc(&gdt[5],&init_task.task.ldt[0],0x40,DA_LDT); //task1的LDT 0x38 _set_gdt_desc(&gdt[7],&task1.task.ldt[0],0x40,DA_LDT); //填充init_task的TSS init_task.task.tss.backlink = 0; init_task.task.tss.esp0=PAGE_SIZE+(long)&init_task; init_task.task.tss.ss0=0x10; init_task.task.tss.eip=&testA; init_task.task.tss.esp = &stack0.top; init_task.task.tss.flags=0x200; init_task.task.tss.es=0x17; init_task.task.tss.cs=0xf; init_task.task.tss.ss=0x17; init_task.task.tss.ds=0x17; init_task.task.tss.fs=0x17; init_task.task.tss.gs=0x18; init_task.task.tss.ldt=0x28; init_task.task.tss.trap=0x8000; init_task.task.tss.iobase=0x0; //init_task的TSS 0x20 _set_gdt_desc(&gdt[4],&init_task.task.tss,0x68,DA_386TSS+DA_DPL3); //填充task1的TSS task1.task.tss.backlink = 0; task1.task.tss.esp0=PAGE_SIZE+(long)&task1;//&stack1_krn_ptr; task1.task.tss.ss0=0x10; task1.task.tss.eip=&testC; task1.task.tss.esp = &stack1.top; task1.task.tss.flags=0x200; task1.task.tss.es=0x17; task1.task.tss.cs=0xf; task1.task.tss.ss=0x17; task1.task.tss.ds=0x17; task1.task.tss.fs=0x17; task1.task.tss.gs=0x18; task1.task.tss.ldt=0x38; task1.task.tss.trap=0x8000; task1.task.tss.iobase=0x0; //task1的TSS 0x30 _set_gdt_desc(&gdt[6],&task1.task.tss,0x68,DA_386TSS+DA_DPL3); //task[1] = &(task1.task); ltr();//加载tss lldt();//加载ldt sti();//开中断 move_to_user_mode(); while(1); }