Linux内核原码分析(main.c)(1)

Linux内核原码分析(main.c)(1),第1张

Linux内核原码分析(main.c)(1)
void main(void)		
{			

 	ROOT_DEV = ORIG_ROOT_DEV;
 	drive_info = DRIVE_INFO;
	memory_end = (1<<20) + (EXT_MEM_K<<10);
	memory_end &= 0xfffff000;
	if (memory_end > 16*1024*1024)
		memory_end = 16*1024*1024;
	if (memory_end > 12*1024*1024) 
		buffer_memory_end = 4*1024*1024;
	else if (memory_end > 6*1024*1024)
		buffer_memory_end = 2*1024*1024;
	else
		buffer_memory_end = 1*1024*1024;
	main_memory_start = buffer_memory_end;
#ifdef RAMDISK
	main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
#endif
	mem_init(main_memory_start,memory_end);
	trap_init();
	blk_dev_init();
	chr_dev_init();
	tty_init();
	time_init();
	sched_init();
	buffer_init(buffer_memory_end);
	hd_init();
	floppy_init();
	sti();
	move_to_user_mode();
	if (!fork()) {		
		init();
	}

	for(;;) pause();
}

1.内核先初始化根设备和硬盘,设置bootsect中读取的软盘为根设备(ROOT_DEV):

    ROOT_DEV = ORIG_ROOT_DEV;

fs/super.c:

int ROOT_DEV = 0;
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)

 2.设置硬盘参数表(drive_info,16字节):

 	drive_info = DRIVE_INFO;
struct drive_info { char dummy[32]; } drive_info;
#define DRIVE_INFO (*(struct drive_info *)0x90080)

3.规划物理内存格局:

	memory_end = (1<<20) + (EXT_MEM_K<<10);
	memory_end &= 0xfffff000;
	if (memory_end > 16*1024*1024)
		memory_end = 16*1024*1024;
	if (memory_end > 12*1024*1024) 
		buffer_memory_end = 4*1024*1024;
	else if (memory_end > 6*1024*1024)
		buffer_memory_end = 2*1024*1024;
	else
		buffer_memory_end = 1*1024*1024;
	main_memory_start = buffer_memory_end;
static long memory_end = 0;
static long buffer_memory_end = 0;
static long main_memory_start = 0;

 

>16MB:           缓冲区4MB, 物理16MB

12~16MB:       缓冲区4MB

6~12MB:         缓冲区2MB

小于6MB:        缓冲区1MB

4.设置虚拟盘空间并初始化:

#ifdef RAMDISK
	main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
#endif

(Makefile)假如设定RAMDISK = 512(单位KB)

 kernel/blk_drv/ramdisk.c:

#define MAJOR_NR 1


long rd_init(long mem_start, int length)
{
	int	i;
	char	*cp;

	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
	rd_start = (char *) mem_start;
	rd_length = length;
	cp = rd_start;
	for (i=0; i < length; i++)
		*cp++ = '';
	return(length);
}

 将blk_dev[1](即dev mem)的request_fn挂上do_rd_request函数(虚拟盘区请求项处理函数)

然后将虚拟盘所在的内存区全部初始化为0

最后返回虚拟盘区的长度值(单位B)

 kernel/blk_drv/ll_rw_blk.c:

struct blk_dev_struct {
	void (*request_fn)(void);
	struct request * current_request;
};


struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
	{ NULL, NULL },		
	{ NULL, NULL },		
	{ NULL, NULL },		
	{ NULL, NULL },		
	{ NULL, NULL },		
	{ NULL, NULL },		
	{ NULL, NULL }		
};

kernel/blk_drv/blk.h:

#define DEVICE_REQUEST do_rd_request



struct request {
	int dev;		
	int cmd;		
	int errors;
	unsigned long sector;
	unsigned long nr_sectors;
	char * buffer;
	struct task_struct * waiting;
	struct buffer_head * bh;
	struct request * next;
};

 kernel/blk_drv/ramdisk.c:

void do_rd_request(void)
{
	int	len;
	char	*addr;

	INIT_REQUEST;
	addr = rd_start + (CURRENT->sector << 9);
	len = CURRENT->nr_sectors << 9;
	if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) {
		end_request(0);
		goto repeat;
	}
	if (CURRENT-> cmd == WRITE) {
		(void ) memcpy(addr,
			      CURRENT->buffer,
			      len);
	} else if (CURRENT->cmd == READ) {
		(void) memcpy(CURRENT->buffer, 
			      addr,
			      len);
	} else
		panic("unknown ramdisk-command");
	end_request(1);
	goto repeat;
}

5.内存管理结构mem_map初始化:

kernel/mm/memory.c:


#define LOW_MEM 0x100000
#define PAGING_MEMORY (15*1024*1024)
#define PAGING_PAGES (PAGING_MEMORY>>12)
#define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
#define USED 100

static long HIGH_MEMORY = 0;

static unsigned char mem_map [ PAGING_PAGES ] = {0,};



void mem_init(long start_mem, long end_mem)
{
	int i;

	HIGH_MEMORY = end_mem;
	for (i=0 ; i>= 12;
	while (end_mem-->0)
		mem_map[i++]=0;      //再将从start_mem到end_mem对应的mem_map置0
}

6.之后进行异常处理类中断服务程序的挂接:

kernel/blk_dev/traps.c:

void trap_init(void)
{
	int i;

	set_trap_gate(0,÷_error);
	set_trap_gate(1,&debug);
	set_trap_gate(2,&nmi);
	set_system_gate(3,&int3);	
	set_system_gate(4,&overflow);
	set_system_gate(5,&bounds);
	set_trap_gate(6,&invalid_op);
	set_trap_gate(7,&device_not_available);
	set_trap_gate(8,&double_fault);
	set_trap_gate(9,&coprocessor_segment_overrun);
	set_trap_gate(10,&invalid_TSS);
	set_trap_gate(11,&segment_not_present);
	set_trap_gate(12,&stack_segment);
	set_trap_gate(13,&general_protection);
	set_trap_gate(14,&page_fault);
	set_trap_gate(15,&reserved);
	set_trap_gate(16,&coprocessor_error);
	for (i=17;i<48;i++)
    set_trap_gate(i,&reserved);
    set_trap_gate(45,&irq13);// 设置协处理器的陷阱门。
    outb_p(inb_p(0x21)&0xfb,0x21);// 允许主8259A 芯片的IRQ2 中断请求。
    outb(inb_p(0xA1)&0xdf,0xA1);// 允许从8259A 芯片的IRQ13 中断请求。
    set_trap_gate(39,¶llel_interrupt);// 设置并行口的陷阱门。

}

TODO: 未追踪IRQ2,3中断设置

include/asm/system.h:

#define _set_gate(gate_addr,type,dpl,addr) 
__asm__ ("movw %%dx,%%axnt"    //addr低位给eax低位
	"movw %0,%%dxnt"           //设置edx低位
	"movl %%eax,%1nt" 
	"movl %%edx,%2" 
	: 
	: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), 
	"o" (*((char *) (gate_addr))), 
	"o" (*(4+(char *) (gate_addr))), 
	"d" ((char *) (addr)),"a" (0x00080000))

#define set_intr_gate(n,addr) 
	_set_gate(&idt[n],14,0,addr)

#define set_trap_gate(n,addr) 
	_set_gate(&idt[n],15,0,addr)

#define set_system_gate(n,addr) 
	_set_gate(&idt[n],15,3,addr)

7.初始化块设备请求项结构:

kernel/blk_drv/ll_rw_blk.c:

void blk_dev_init(void)
{
	int i;

	for (i=0 ; i 

kernel/blk_drv/blk.h:

#define NR_REQUEST	32


struct request {
	int dev;		
	int cmd;		
	int errors;
	unsigned long sector;
	unsigned long nr_sectors;
	char * buffer;
	struct task_struct * waiting;
	struct buffer_head * bh;
	struct request * next;
};




8.初始化字符设备请求项结构:

kernel/chr_dev/tty_io.c:

void chr_dev_init(void)
{
}

空,实际上是通过tty_init来初始化的

kernel/chr_dev/tty_io.c:

void tty_init(void)
{
	rs_init();   //对串行口进行设置
	con_init();  //
}

kernel/chr_dev/serial.c:

void rs_init(void)
{
	set_intr_gate(0x24,rs1_interrupt);   //设置串行口1中断
	set_intr_gate(0x23,rs2_interrupt);   //设置串行口2中断
	init(tty_table[1].read_q.data);      //初始化串行口1
	init(tty_table[2].read_q.data);      //初始化串行口2
	outb(inb_p(0x21)&0xE7,0x21);         //允许IRQ3,IRQ4
}


static void init(int port)
{
	outb_p(0x80,port+3);	
	outb_p(0x30,port);	
	outb_p(0x00,port+1);	
	outb_p(0x03,port+3);	
	outb_p(0x0b,port+4);	
	outb_p(0x0d,port+1);	
	(void)inb(port);	
}

include/linux/tty.h:

struct tty_struct {
	struct termios termios;
	int pgrp;
	int stopped;
	void (*write)(struct tty_struct * tty);
	struct tty_queue read_q;
	struct tty_queue write_q;
	struct tty_queue secondary;
	};

extern struct tty_struct tty_table[];

kernel/chr_dev/tty_io.c:

struct tty_struct tty_table[] = {
	{
		{ICRNL,		
		OPOST|ONLCR,	
		0,
		ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
		0,		
		INIT_C_CC},
		0,			
		0,			
		con_write,
		{0,0,0,0,""},		
		{0,0,0,0,""},		
		{0,0,0,0,""}		
	},{
		{0, 
		0,  
		B2400 | CS8,
		0,
		0,
		INIT_C_CC},
		0,
		0,
		rs_write,
		{0x3f8,0,0,0,""},		
		{0x3f8,0,0,0,""},
		{0,0,0,0,""}
	},{
		{0, 
		0,  
		B2400 | CS8,
		0,
		0,
		INIT_C_CC},
		0,
		0,
		rs_write,
		{0x2f8,0,0,0,""},		
		{0x2f8,0,0,0,""},
		{0,0,0,0,""}
	}
};


struct tty_queue * table_list[]={
	&tty_table[0].read_q, &tty_table[0].write_q,
	&tty_table[1].read_q, &tty_table[1].write_q,
	&tty_table[2].read_q, &tty_table[2].write_q
	};

TODO:未细究

kernel//chr_drv/console.c:

void con_init(void)
{
	register unsigned char a;
	char *display_desc = "????";
	char *display_ptr;

	video_num_columns = ORIG_VIDEO_COLS;
	video_size_row = video_num_columns * 2;
	video_num_lines = ORIG_VIDEO_LINES;
	video_page = ORIG_VIDEO_PAGE;
	video_erase_char = 0x0720;
	
	if (ORIG_VIDEO_MODE == 7)			
	{
		video_mem_start = 0xb0000;
		video_port_reg = 0x3b4;
		video_port_val = 0x3b5;
		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
		{
			video_type = VIDEO_TYPE_EGAM;
			video_mem_end = 0xb8000;
			display_desc = "EGAm";
		}
		else
		{
			video_type = VIDEO_TYPE_MDA;
			video_mem_end	= 0xb2000;
			display_desc = "*MDA";
		}
	}
	else								
	{
		video_mem_start = 0xb8000;
		video_port_reg	= 0x3d4;
		video_port_val	= 0x3d5;
		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
		{
			video_type = VIDEO_TYPE_EGAC;
			video_mem_end = 0xbc000;
			display_desc = "EGAc";
		}
		else
		{
			video_type = VIDEO_TYPE_CGA;
			video_mem_end = 0xba000;
			display_desc = "*CGA";
		}
	}

	
	
	display_ptr = ((char *)video_mem_start) + video_size_row - 8;
	while (*display_desc)
	{
		*display_ptr++ = *display_desc++;
		display_ptr++;
	}
	
	
	
	origin	= video_mem_start;
	scr_end	= video_mem_start + video_num_lines * video_size_row;
	top	= 0;
	bottom	= video_num_lines;

	gotoxy(ORIG_X,ORIG_Y);
	set_trap_gate(0x21,&keyboard_interrupt);
	outb_p(inb_p(0x21)&0xfd,0x21);
	a=inb_p(0x61);
	outb_p(a|0x80,0x61);
	outb(a,0x61);
}

TODO:未细究

9.开机启动时间设置:

main.c:

static void time_init(void)
{
	struct tm time;

	do {
		time.tm_sec = CMOS_READ(0);
		time.tm_min = CMOS_READ(2);
		time.tm_hour = CMOS_READ(4);
		time.tm_mday = CMOS_READ(7);
		time.tm_mon = CMOS_READ(8);
		time.tm_year = CMOS_READ(9);
	} while (time.tm_sec != CMOS_READ(0));
	BCD_TO_BIn(time.tm_sec);
	BCD_TO_BIn(time.tm_min);
	BCD_TO_BIn(time.tm_hour);
	BCD_TO_BIn(time.tm_mday);
	BCD_TO_BIn(time.tm_mon);
	BCD_TO_BIn(time.tm_year);
	time.tm_mon--;
	startup_time = kernel_mktime(&time);
}

TODO:未细究

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5502179.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存