初始化进程0:
kernel/sched.c:
void sched_init(void)
{
int i;
struct desc_struct * p;
if (sizeof(struct sigaction) != 16)
panic("Struct sigaction MUST be 16 bytes");
set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); //设置TSS0
set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); //设置TSS1
p = gdt+2+FIRST_TSS_ENTRY; //从GDT的6项,即TSS1开始向上全部清零
for(i=1;i<NR_TASKS;i++) { //并且将进程槽从1往后的项清空。0项为进程0所用
task[i] = NULL;
p->a=p->b=0;
p++;
p->a=p->b=0;
p++;
}
/* Clear NT, so that we won't have troubles with that later on */
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
ltr(0); //重要!将TSS挂接到TR寄存器
lldt(0); //重要!将LDT挂接到LDTR寄存器
outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ //设置定时器
outb_p(LATCH & 0xff , 0x40); /* LSB */ //每10毫秒一次时钟中断
outb(LATCH >> 8 , 0x40); /* MSB */
set_intr_gate(0x20,&timer_interrupt); //重要!设置时钟中断,进程调度的基础
outb(inb_p(0x21)&~0x01,0x21); //允许时钟中断
set_system_gate(0x80,&system_call); //重要!设置系统调用总入口
}
include/linux/sched.h:
#define FIRST_TSS_ENTRY 4
include/asm/system.h:
#define _set_tssldt_desc(n,addr,type) \
__asm__ ("movw $104,%1\n\t" \ //1101000存入第1、2字节
"movw %%ax,%2\n\t" \ //tss或ldt低位存入第3、4字节
"rorl $16,%%eax\n\t" \ //循环右移16位,即高低互换
"movb %%al,%3\n\t" \ //即将tss或ldt地址第3字节存入第5字节
"movb $" type ",%4\n\t" \ //将0x89或0x82存入第6字节
"movb $0x00,%5\n\t" \ //将0x00存入第7字节
"movb %%ah,%6\n\t" \ //即将tss或ldt地址第4字节存入第8字节
"rorl $16,%%eax" \ //复原eax
::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
"m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
)
#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")
初始化缓冲区管理结构:
fs/buffer.c:
extern int end;
struct buffer_head * start_buffer = (struct buffer_head *) &end;
void buffer_init(long buffer_end)
{
struct buffer_head * h = start_buffer;
void * b;
int i;
if (buffer_end == 1<<20)
b = (void *) (640*1024);
else
b = (void *) buffer_end;
while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
h->b_dev = 0;
h->b_dirt = 0;
h->b_count = 0;
h->b_lock = 0;
h->b_uptodate = 0;
h->b_wait = NULL;
h->b_next = NULL;
h->b_prev = NULL;
h->b_data = (char *) b;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
NR_BUFFERS++;
if (b == (void *) 0x100000)
b = (void *) 0xA0000;
}
h--;
free_list = start_buffer;
free_list->b_prev_free = h;
h->b_next_free = free_list;
for (i=0;i<NR_HASH;i++)
hash_table[i]=NULL;
}
include/linux/fs.h:
struct buffer_head {
char * b_data; /* pointer to data block (1024 bytes) */
unsigned long b_blocknr; /* block number */
unsigned short b_dev; /* device (0 = free) */
unsigned char b_uptodate;
unsigned char b_dirt; /* 0-clean,1-dirty */
unsigned char b_count; /* users using this block */
unsigned char b_lock; /* 0 - ok, 1 -locked */
struct task_struct * b_wait;
struct buffer_head * b_prev;
struct buffer_head * b_next;
struct buffer_head * b_prev_free;
struct buffer_head * b_next_free;
};
初始化硬盘:
kernel/blk_drv/hd.c:
#define MAJOR_NR 3
void hd_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; //do_hd_request
set_intr_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21); //允许8259A发出中断请求
outb(inb_p(0xA1)&0xbf,0xA1); //允许硬盘发送中断请求
}
初始化软盘:
kernel/blk_drv/floppy.c:
#define MAJOR_NR 2
void floppy_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_trap_gate(0x26,&floppy_interrupt);
outb(inb_p(0x21)&~0x40,0x21); //允许软盘发送中断
}
中断服务程序构建完毕,开中断:
sti();
进程0由0特权级跳转至3特权级:
#define move_to_user_mode() \ //模仿中断硬件压栈,顺序是ss、esp、eflags、cs、eip
__asm__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \ //ss进栈,即10111(3特权级,LDT,数据段)
"pushl %%eax\n\t" \ //esp进栈
"pushfl\n\t" \ //eflags进栈
"pushl $0x0f\n\t" \ //cs进栈,即1111(3特权级,LDT,代码段)
"pushl $1f\n\t" \ //eip进栈
"iret\n" \ //出栈恢复现场,翻转特权级
"1:\tmovl $0x17,%%eax\n\t" \ //下面代码使ds,es,fs,gs与ss一致
"movw %%ax,%%ds\n\t" \
"movw %%ax,%%es\n\t" \
"movw %%ax,%%fs\n\t" \
"movw %%ax,%%gs" \
:::"ax")