//启动系统内核
//asmlinkage 为通过堆栈传递参数,默认为通过寄存器传递参数。
asmlinkage void start_kernel(void)
{
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
//设置中断向量表
set_call_gate(&default_ldt,lcall7);
//设定初始化设备地址
ROOT_DEV = ORIG_ROOT_DEV;
// 设定设备信息地址
drive_info = DRIVE_INFO;
//设定屏幕信息地址
screen_info = SCREEN_INFO;
//设定aux 设备当前地址
aux_device_present = AUX_DEVICE_INFO;
//设定内存末端值
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= PAGE_MASK;
//设定临时盘的大小
ramdisk_size = RAMDISK_SIZE;
//拷贝命令行
copy_options(command_line,COMMAND_LINE);
//如果内存大于16M 设定内存末端为16M
#ifdef CONFIG_MAX_16M
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
#endif
//设定root 的多位标志位
if (MOUNT_ROOT_RDONLY)
root_mountflags |= MS_RDONLY;
//如果最末端大于1M 设定内存开始点和最低内存开始点
if ((unsigned long)&end >= (1024*1024)) {
memory_start = (unsigned long) &end;
low_memory_start = PAGE_SIZE;
}
else
{
//如果内存不大于1M ;设定内存开始点为1M处, 最低内存开始为end;
memory_start = 1024*1024;
low_memory_start = (unsigned long) &end;
}
//低内存开始点对齐
low_memory_start = PAGE_ALIGN(low_memory_start);
//页缓存区初始化
memory_start = paging_init(memory_start,memory_end);
//设定EISA 线路标志
if (strncmp((char*)0x0FFFD9, "EISA", 4) == 0)
EISA_bus = 1;
//设置各个中断向量表.
trap_init();
//初始化中断请求
init_IRQ();
//日程初始化
sched_init();
//解析命令行
parse_options(command_line);
#ifdef CONFIG_PROFILE
prof_buffer = (unsigned long *) memory_start;
prof_len = (unsigned long) &end;
prof_len >>= 2;
memory_start += prof_len * sizeof(unsigned long);
#endif
//分配内存 初始化
memory_start = kmalloc_init(memory_start,memory_end);
//
memory_start = chr_dev_init(memory_start,memory_end);
memory_start = blk_dev_init(memory_start,memory_end);
//设定允许中断
sti();
//校准延时
calibrate_delay();
#ifdef CONFIG_INET
//网络初始化
memory_start = net_dev_init(memory_start,memory_end);
#endif
#ifdef CONFIG_SCSI
//scsi 设备初始化
memory_start = scsi_dev_init(memory_start,memory_end);
#endif
//节点初始化
memory_start = inode_init(memory_start,memory_end);
//文件表初始化
memory_start = file_table_init(memory_start,memory_end);
//内存区初始化
mem_init(low_memory_start,memory_start,memory_end);
//缓存初始化
buffer_init();
// 时间初始化
time_init();
//软盘初始化
floppy_init();
//sock 初始化
sock_init();
#ifdef CONFIG_SYSVIPC
//ipc 初始化
ipc_init();
#endif
//设定允许中断
sti();
/*
* check if exception 16 works correctly.. This is truly evil
* code: it disables the high 8 interrupts to make sure that
* the irq13 doesn't happen. But as this will lead to a lockup
* if no exception16 arrives, it depends on the fact that the
* high 8 interrupts will be re-enabled by the next timer tick.
* So the irq13 will happen eventually, but the exception 16
* should get there first..
*/
//hard_math设定为是时进行响应处理
if (hard_math) {
unsigned short control_word;
printk("Checking 386/387 coupling... ");
timer_table[COPRO_TIMER].expires = jiffies+50;
timer_table[COPRO_TIMER].fn = copro_timeout;
timer_active |= 1<<COPRO_TIMER;
__asm__("clts ; fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
control_word &= 0xffc0;
__asm__("fldcw %0 ; fwait": :"m" (*&control_word));
outb_p(inb_p(0x21) | (1 << 2), 0x21);
__asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
timer_active &= ~(1<<COPRO_TIMER);
if (!fpu_error)
printk("Ok, fpu using %s error reporting.\n",
ignore_irq13?"exception 16":"irq13");
}
//如果没有设定数字仿真设定进行报错
#ifndef CONFIG_MATH_EMULATION
else {
printk("No coprocessor found and no math emulation present.\n");
printk("Giving up.\n");
for (;;) ;
}
#endif
//设定系统版本 并打印出来
system_utsname.machine[1] = '0' + x86;
printk(linux_banner);
//设定到用户模式
move_to_user_mode();
//初始化完成, 创建子进程进入到shell界面.
if (!fork()) /* we count on this going ok */
init();
/*
* task[0] is meant to be used as an "idle" task: it may not sleep, but
* it might do some general things like count free pages or it could be
* used to implement a reasonable LRU algorithm for the paging routines:
* anything that can be useful, but shouldn't take time from the real
* processes.
*
* Right now task[0] just does a infinite idle loop.
*/
//父进程进行休眠。
for(;;)
idle();
}
void start_kernel(void)分析 ! \linux-1.0\init\main.c
最新推荐文章于 2024-09-15 15:04:39 发布