Linux内核源代码分析一(Linux0.12)
Linux 内核主要由 5 个模块构成,它们分别是:进程调度模块、内存管理模块、文件系统模块、进程间通信模块和网络接口模块。
1.引导启动程序(boot)
首先说一下pc机的启动流程,在加电后,80X86会先进入实模式并进入地址0XFFFF0开始自动执行代码,这个地址一般带表了BIOS的代码地址,PC的BIOS将会执行硬件检测和诊断功能,并在0地址进行中断向量的初始化,最后BIOS会将启动设备的第一个扇区读入地址0X7C00位置,并从这个位置开始执行代码。
boot目录下包含三个汇编代码文件
Bootsect.s
bootsect文件是在记录在磁盘的第一个扇区中,BIOS系统会将其加载到0X7C00的位置并执行。
在bootsect.s文件中做的主要的事情如下:
1.将自身移动到0X9000位置,这一步主要是为了后面讲head和setup的代码放到boot sect上面
entry start
start:
mov ax,#BOOTSEG
mov ds,ax
mov ax,#INITSEG
mov es,ax
mov cx,#256
sub si,si
sub di,di
rep
movw
jmpi go,INITSEG
2.是利用 ROM BIOS 中断 INT 0x13 将 setup 模块从磁盘第 2 个扇区开始读到0x90200 开始处,共读 4 个扇区。在读操作过程中如果读出错,则显示磁盘上出错扇区位置,然后复位驱动器并重试,没有退路。
load_setup:
xor dx, dx ! drive 0, head 0
mov cx,#0x0002 ! sector 2, track 0
mov bx,#0x0200 ! address = 512, in INITSEG
mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors
int 0x13 ! read it
jnc ok_load_setup ! ok - continue
push ax ! dump error code
call print_nl
mov bp, sp
call print_hex
pop ax
xor dl, dl ! reset FDC
xor ah, ah
int 0x13
j load_setup
ok_load_setup:
3.将 system 模块加载到 0x10000(64KB)开始处
4.检查要使用哪个根文件系统设备
5.到此,所有程序都加载完毕,我们就跳转到被加载在 bootsect 后面的 setup 程序去。
Setup.s
setup.s的主要作用如下:
1.通过BIOS系统调用(0X13)获取系统参数并将系统参数存储在0X90000的位置(原存放bootsect.s的位置)
2.初始化GDT(全局表述表)和IDT(中断表述表)以及GDTR和IDTR寄存器
3.将system模块从bootsect.s加载进来的位置,移动到0X00000的位置
Head.s
head.s被作为system的一部分并置于system的头部,所以被命名为head,其次还负责将eip指向main.c从而执行main.c进行系统中各个模块的初始化。
2.初始化程序(init)
init目录下仅存在一个main.c文件,系统在执行完 boot/head.s 程序后就会将执行权交给 main.c。该程序虽然不长,但却包括了内核初始化的所有工作。
main.c的主体流程可以从main方法来看
1.将setup.s获取的系统参数从0X90080处取出并存到内核的全局变量中
2.计算内存的结束位置,也就是计算memory_end(机器具有的物理内存容量(字节数))的大小
3.根据物理内存容:量计算高速缓冲区的大小(buffer_memory_end)
4.计算主内存的起始位置,main_memory_start代表了主内存的位置
此时内存的分布为:system(内核程序)->高速缓冲区->虚拟盘(如果有的话)->主内存
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();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)