int k_reenter = -1;
// Descriptor
typedef struct descriptor {
short limit_low;
short base_low;
char base_mid;
char access_right;
char limit_high;
char base_high;
}descriptor, *Descriptor;
typedef struct gate {
short offset_low;
short selector;
char dw_count;
char access_right;
short offset_high;
}gate, *Gate;
// start process data struct
typedef struct tss {
int backlink;
int esp0;
int ss0;
int esp1;
int ss1;
int esp2;
int ss2;
int cr3;
int eip;
int eflags;
int eax;
int ecx;
int edx;
int ebx;
int esp;
int ebp;
int esi;
int edi;
int es;
int cs;
int ss;
int ds;
int fs;
int gs;
int ldt_sel;
short trap;
short iobase;
}tss, *Tss;
typedef struct proc_stack {
int gs;
int fs;
int es;
int ds;
int edi;
int esi;
int ebp;
int kernel_esp;
int ebx;
int edx;
int ecx;
int eax;
int retaddr;
int eip;
int cs;
int eflags;
int esp;
int ss;
}proc_stack;
typedef struct process {
proc_stack procstack;
short ldt_selector;
descriptor ldt[0x10];
int pid;
char name[32];
unsigned int ticks;
unsigned int priority;
}process, *Process;
// end process data struct
void print_s(char *str, char color, int j);
void halt(void);
void delay(int count);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
void asm_inthandler_all(void);
void asm_inthandler_0xd(void);
void asm_inthandler_0x20(void);
void asm_inthandler_0x21(void);
void ud2(void);
void testa(void);
void testb(void);
void testc(void);
void testd(void);
void teste(void);
void testf(void);
void testg(void);
void testh(void);
void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib);
void set_gate(Gate gd, int offset, int selector, int attrib);
// S:copy from multiboot2 os example.
#define COLUMNS 80
#define LINES 24
#define ATTRIBUTE 7
#define VIDEO 0xb8000
static int xpos;
static int ypos;
static volatile unsigned char *video;
static void cls (void);
static void itoa (char *buf, int base, int d);
static void putchar (int c);
void printf (const char *format, ...);
void out(int port, int value);
int in(int port);
void sti(void);
void cli(void);
void init_8259a(void);
void init_8254(void);
int mycount = 0;
char *func_stack = (char *)0x800000;
process p_proc[8];
Process p_proc_ready, myproc;
tss tss0;
Tss mytss = &tss0;
typedef void (*task_f)(void);
typedef struct s_task {
task_f initial_eip;
int stacksize;
char name[0x20];
}task, *Task;
task task_table[8] = {{testa, 0x400, "testa"}, \
{testb, 0x400, "testb"}, \
{testc, 0x400, "testc"}, \
{testd, 0x400, "testd"}, \
{teste, 0x400, "teste"}, \
{testf, 0x400, "testf"}, \
{testg, 0x400, "testg"}, \
{testh, 0x400, "testh"}};
void goto_ring3(void);
void ltr(int tr);
void init_tss(Tss mytss, Descriptor mygdt);
void init_proc_table(Process myproc, Task mytask, Descriptor mygdt);
void schedule(Process p);
int kernel_main(int eax, int ebx) {
cls();
Process myproc;
myproc = p_proc;
Descriptor mygdt = (Descriptor) 0x7c00;
Gate myidt = (Gate) 0x0;
set_descriptor(mygdt + 0, 0, 0, 0); //0 * 8
set_descriptor(mygdt + 1, 0xffffffff, 0x0, 0xc09a); //1 * 8
set_descriptor(mygdt + 2, 0xffffffff, 0x0, 0xc092); //2 * 8
load_idtr(256 * 8 - 1, (int) myidt);
load_gdtr(256 * 8 - 1, (int) mygdt);
Task p_task = task_table;
init_proc_table(myproc, p_task, mygdt);
int i;
for(i = 0; i < 256; i++) {
set_gate(myidt + i, (int) asm_inthandler_all, 0x8, 0x8e);
}
set_gate(myidt + 0xd, (int) asm_inthandler_0xd, 0x8, 0x8e);
set_gate(myidt + 0x20, (int) asm_inthandler_0x20, 1 * 8, 0x8e);
set_gate(myidt + 0x21, (int) asm_inthandler_0x21, 1 * 8, 0x8e);
// set_gate(myidt + 0x80, (int) system_interrupt, 1 * 8, 0xee);
init_tss(mytss, mygdt);
init_8259a();
init_8254();
out(0x21, 0xf8);
out(0xa1, 0xff);
p_proc_ready = p_proc;
goto_ring3();
while(1) {
print_s("Sys!", 0xf, 17);
}
return 0;
}
void print_s(char *str, char color, int j) {
int i = 0;
while(*str) {
while(*str == '\n') {
str++;
i = 0;
j++;
}
if(!(*str)) {
return;
}
*(video + i + j * 80 * 2) = *str++;
*(video + i + 1 + j * 80 * 2) = color;
i += 2;
}
return;
}
/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
static void cls (void) {
int i;
video = (unsigned char *) VIDEO;
for (i = 0; i < COLUMNS * LINES * 2; i++)
*(video + i) = 0;
xpos = 0;
ypos = 0;
return;
}
/* Convert the integer D to a string and save the string in BUF. If
BASE is equal to 'd', interpret that D is decimal, and if BASE is
equal to 'x', interpret that D is hexadecimal. */
static void itoa (char *buf, int base, int d) {
char *p = buf;
char *p1, *p2;
unsigned long ud = d;
int divisor = 10;
/* If %d is specified and D is minus, put `-' in the head. */
if (base == 'd' && d < 0) {
*p++ = '-';
buf++;
ud = -d;
}
else if (base == 'x')
divisor = 16;
/* Divide UD by DIVISOR until UD == 0. */
do {
int remainder = ud % divisor;
*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
} while (ud /= divisor);
/* Terminate BUF. */
*p = 0;
/* Reverse BUF. */
p1 = buf;
p2 = p - 1;
while (p1 < p2) {
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
}
/* Put the character C on the screen. */
static void putchar (int c) {
if (c == '\n' || c == '\r') {
newline:
xpos = 0;
ypos++;
if (ypos >= LINES)
ypos = 0;
return;
}
*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
*(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
xpos++;
if (xpos >= COLUMNS)
goto newline;
}
/* Format a string and print it on the screen, just like the libc
function printf. */
void printf (const char *format, ...) {
char **arg = (char **) &format;
int c;
char buf[20];
arg++;
while ((c = *format++) != 0) {
if (c != '%')
putchar (c);
else {
char *p, *p2;
int pad0 = 0, pad = 0;
c = *format++;
if (c == '0') {
pad0 = 1;
c = *format++;
}
if (c >= '0' && c <= '9')
{
pad = c - '0';
c = *format++;
}
switch (c) {
case 'd':
case 'u':
case 'x':
itoa (buf, c, *((int *) arg++));
p = buf;
goto string;
break;
case 's':
p = *arg++;
if (! p)
p = "(null)";
string:
for (p2 = p; *p2; p2++);
for (; p2 < p + pad; p2++)
putchar (pad0 ? '0' : ' ');
while (*p)
putchar (*p++);
break;
default:
putchar (*((int *) arg++));
break;
}
}
}
}
void *memcpy(void *dest, void *source, int count) {
int i;
void *temp = dest;
for(i = 0; i < count; i++) {
*((char *)dest++) = *((char *)source++);
}
return temp;
}
void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib) {
if(limit > 0xfffff) {
attrib |= 0x8000;
limit /= 0x1000;
}
sd->limit_low = limit & 0xffff;
sd->base_low = base & 0xffff;
sd->base_mid = (base >> 16) & 0xff;
sd->access_right = attrib & 0xff;
sd->limit_high = ((limit >> 16) & 0x0f) | ((attrib >> 8) & 0xf0);
sd->base_high = (base >> 24) & 0xff;
return;
}
void set_gate(Gate gd, int offset, int selector, int attrib) {
gd->offset_low = offset & 0xffff;
gd->selector = selector;
gd->dw_count = (attrib >> 8) & 0xff;
gd->access_right = attrib & 0xff;
gd->offset_high = (offset >> 16) & 0xffff;
return;
}
void inthandler_all(int *esp) {
printf("Exception! 0x%x", esp);
while(1) {
halt();
}
return;
}
void inthandler_0xd(int *esp) {
printf("general protection! 0x%x", esp);
while(1) {
halt();
}
return;
}
void inthandler_0x21(int *esp) {
out(0x20, 0x61);
int key = in(0x60);
char buf[0x40];
print_s("keyboard interrupt!", 0xf, 21);
print_s(" ", 0xf, 22);
itoa(buf, 10, key);
print_s(buf, 0xf, 22);
return;
}
int ia = 0;
void testa(void) {
char buf[0x20];
while (1) {
print_s("testa", 0x9, 0);
itoa(buf, 10, ia++);
print_s(buf, 0x9, 1);
// delay(0xfffff);
}
return;
}
int ib = 0;
void testb(void) {
char buf[0x20];
while (1) {
print_s("testb", 0xd, 2);
itoa(buf, 10, ib++);
print_s(buf, 0xd, 3);
// delay(0xfff);
}
return;
}
int ic = 0;
void testc(void) {
char buf[0x20];
while (1) {
print_s("testc", 0xf, 4);
itoa(buf, 10, ic++);
print_s(buf, 0xf, 5);
// delay(0x888);
}
return;
}
int id = 0;
void testd(void) {
char buf[0x20];
while (1) {
print_s("testd", 0xe, 6);
itoa(buf, 10, id++);
print_s(buf, 0xe, 7);
// delay(0x88);
}
return;
}
int ie = 0;
void teste(void) {
char buf[0x20];
while (1) {
print_s("teste", 0x4, 8);
itoa(buf, 10, ie++);
print_s(buf, 0x4, 9);
// delay(0xffff);
}
return;
}
int iff = 0;
void testf(void) {
char buf[0x20];
while (1) {
print_s("testf", 0x8, 10);
itoa(buf, 10, iff++);
print_s(buf, 0x8, 11);
// delay(0xf);
}
return;
}
int ig = 0;
void testg(void) {
char buf[0x20];
while (1) {
print_s("testg", 0x6, 12);
itoa(buf, 10, ig++);
print_s(buf, 0x6, 13);
// delay(0xaaaaa);
}
return;
}
int ih = 0;
void testh(void) {
char buf[0x20];
while (1) {
print_s("testh", 0x7, 14);
itoa(buf, 10, ih++);
print_s(buf, 0x7, 15);
// delay(0xccc);
}
return;
}
void init_8254(void) {
out(0x43, 0x36);
out(0x40, 0x9c);
out(0x40, 0x2e);
return;
}
void init_proc_table(Process myproc, Task mytask, Descriptor mygdt) {
int i;
for(i = 0; i < 8; i++) {
myproc->ticks = myproc->priority = 2 + i;
myproc->pid = i;
myproc->ldt_selector = (3 + i) * 8;
set_descriptor(mygdt + (3 + i), 8 * 0x10 - 1, (int)myproc->ldt, 0xc0e2);
set_descriptor(myproc->ldt + 0, 0xffffffff, 0x0, 0xc0fa); //0 * 8 + 7
set_descriptor(myproc->ldt + 1, 0xffffffff, 0x0, 0xc0f2); //1 * 8 + 7
myproc->procstack.gs = 0xf;
myproc->procstack.fs = 0xf;
myproc->procstack.es = 0xf;
myproc->procstack.ds = 0xf;
myproc->procstack.edi = 0x0;
myproc->procstack.esi = 0x0;
myproc->procstack.ebp = 0x0;
myproc->procstack.kernel_esp = 0;
myproc->procstack.ebx = 0x0;
myproc->procstack.edx = 0x0;
myproc->procstack.ecx = 0x0;
myproc->procstack.eax = 0x0;
myproc->procstack.retaddr = 0x0;
myproc->procstack.eip = (int)mytask->initial_eip;
myproc->procstack.cs = 0x7;
myproc->procstack.eflags = 0x202;
myproc->procstack.esp = (int)func_stack;
myproc->procstack.ss = 0xf;
myproc++;
mytask++;
func_stack -= 0x400;
}
return;
}
void init_tss(Tss mytss, Descriptor mygdt) {
set_descriptor(mygdt + 20, sizeof(tss0), (int)mytss, 0xc0e9); //20 * 8
mytss->backlink = 0;
mytss->esp0 = 0;
mytss->ss0 = 2 * 8;
mytss->esp1= 0;
mytss->ss1 = 0;
mytss->esp2 = 0;
mytss->ss2 = 0;
mytss->cr3 = 0;
mytss->eflags = 0;
mytss->eax = 0;
mytss->ecx = 0;
mytss->edx = 0;
mytss->esp = 0;
mytss->ebp = 0;
mytss->esi = 0;
mytss->edi = 0;
mytss->es = 0xf;
mytss->cs = 0x7;
mytss->ss = 0xf;
mytss->ds = 0xf;
mytss->fs = 0xf;
mytss->gs = 0xf;
mytss->ldt_sel = 0;
mytss->trap = 0;
mytss->iobase = sizeof(tss);
ltr(20 * 8);
return;
}
void inthandler_0x20(int *esp) {
char buf[0x40];
print_s("timer interrupt!", 0xc, 23);
itoa(buf, 10, mycount++);
print_s(buf, 0xc, 24);
p_proc_ready->ticks--;
if(p_proc_ready->ticks > 0)
return;
schedule(p_proc);
return;
}
void schedule(Process p) {
// p_proc_ready++; // 时间片轮转法
// if(p_proc_ready >= p_proc + 8)
// p_proc_ready = p_proc;
int myticks = 0; // 简单优先级法
while(!myticks) {
for(p = p_proc; p < p_proc + 8; p++) {
if(p->ticks > myticks) {
myticks = p->ticks;
p_proc_ready = p;
}
}
if(!myticks) {
for(p = p_proc; p < p_proc + 8; p++) {
p->ticks = p->priority;
}
}
}
return;
}
加入了基于简单优先级的任务调度,看着好像跟时间片轮转没什么区别
猜你喜欢
转载自blog.csdn.net/weixin_39410618/article/details/84593745
今日推荐
周排行