Linux0.11内核源码分析(main.c)(2)

初始化进程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")

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值