一上电,硬件强制让cpu的cs:ip寄存器指向bios程序的位置,从bios程序开始执行,由pc机的BIOS (0xFFFFO是BIOs存储的总线地址)把bootsect从某个固定的地址拿到了内存中的某个固定地址(0x90000),并且进行了一系列的硬件初始化和参数设置----bois可以存储着大量的硬件参数
bootsect.s位于启动区的第一个扇区
作用:首先将后续的setup.s代码从磁盘中加载到紧接着bootsect.s的地方。
在显示屏上显示loading system(操作系统)模块加载到ox10000的地方最后跳转到setup.s中去运行
setup.s位于启动区的2~5扇区
解析BIOS/BOOTLOADER传递来的参数设置系统内核运行的LDT(局部描述符)IDT(中断描述符寄存器)全局描述符(设置全局描述符寄存器)设置中断控制芯片,进入保护模式运行(svc32保护模式设置寄存器中的值)跳转到system模块的最前面的代码运行(head.s)
重点:很多全局变量的属性值,都是由这里解析出来设置的,比如内存大小,内存位置这些环境属性值等等(全局变量 都是在boot阶段读入的,然后放到宏定义中)
head.s大小240个扇区
加载内核运行时的各数据段寄存器,重新设置中断描述符表开启内核正常运行时的协处理器等资源设置内存管理的分页机制跳转到main.c开始运行
//main函数 linux引导成功后就从这里开始运行
void main(void) /* This really IS void, no error here. */
{ /* The startup routine assumes (well, ...) this */
/** Interrupts are still disabled. Do necessary setups, then* enable them*/
//前面这里做的所有事情都是在对内存进行拷贝ROOT_DEV = ORIG_ROOT_DEV;//设置操作系统的根文件drive_info = DRIVE_INFO;//设置操作系统驱动参数//解析setup.s代码后获取系统内存参数memory_end = (1<<20) + (EXT_MEM_K<<10);//取整4k的内存大小memory_end &= 0xfffff000;if (memory_end > 16*1024*1024)//控制操作系统的最大内存为16Mmemory_end = 16*1024*1024;if (memory_end > 12*1024*1024) buffer_memory_end = 4*1024*1024;//设置高速缓冲区的大小,跟块设备有关,跟设备交互的时候,充当缓冲区,写入到块设备中的数据先放在缓冲区里,只有执行sync时才真正写入;这也是为什么要区分块设备驱动和字符设备驱动;块设备写入需要缓冲区,字符设备不需要是直接写入的else if (memory_end > 6*1024*1024)buffer_memory_end = 2*1024*1024;elsebuffer_memory_end = 1*1024*1024;main_memory_start = buffer_memory_end;
#ifdef RAMDISKmain_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()) { //创建0号进程 fork函数就是用来创建进程的函数 /* we count on this going ok *///0号进程是所有进程的父进程init();}
/** NOTE!! For any other task 'pause()' would mean we have to get a* signal to awaken, but task0 is the sole exception (see 'schedule()')* as task 0 gets activated at every idle moment (when no other tasks* can run). For task0 'pause()' just means we go check if some other* task can run, and if not we return here.*/
//0号进程永远不会结束,他会在没有其他进程调用的时候调用,只会执行for(;;) pause();for(;;) pause();
}
写文件,先进入高速缓冲区,由高速缓冲区内存。内存规划