//启动系统内核
//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_16Mif (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_PROFILEprof_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_EMULATIONelse {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();
}