Study Linux Kernel Notes(v 0.11) Shawn.Xie
Shawshie@msn.com
4 main.c
4.1 function: main()
4.1.1 Procedure Overview
(1) 在全局变量中保存根设备号、磁盘驱动器的信息等。
(2) 初始化内存空间的大致分配:
内存末端 = 1M + 扩展内存大小,并进行页对齐(4096)
内存末端 > 16M, 内存末端 = 16M
内存末端 > 12M, 缓冲区末端 = 4M
内存末端 > 6M && <= 12M,缓冲区末端 = 2M
内存末端 < 6M, 缓冲区末端 = 1M
RAM
| |
+--------------+ memory_end
| |
+--------------+ main_memory_start (if RAMDISK = 0, main_memory_start = buffer_memory_end)
| | RAMDISK * 1024
+--------------+ buffer_memory_end
| |
(3) Call mem_init(),内存管理初始化
mem_map[0...Start_mem/4K-1] = USED;
mem_map[Start_mem/4K...16M/4K-1] = 0;
(4) Call trap_init(),陷阱门初始化
将相关ISR挂到陷阱门中(0-16,45 used. 17-44,46-47 reserved)
允许主8259A 芯片的IRQ2 中断请求。
允许从8259A 芯片的IRQ13 中断请求。
将相关ISR挂到陷阱门中(39)
(5) Call blk_dev_init(),块设备初始化
request[0...31].dev = -1; (设备没有请求)
request[0...31].next = NULL;
(6) Call chr_dev_init(),字符设备初始化
NULL
(7) Call tty_init(),tty初始化
初始化串口终端
初始化控制台终端
(8) Call time_init(),计算机时间初始化
从BIOS中获取机器时间,将BCD码转换成二进制
将时间转换成自1970年以来累计运行的秒数
(9) Call sched_init(),调度初始化
--------------------------------------------------------------------
局部描述符表描述符详解:
63 56 55 54 53 52 51 48 47 46 45 44 43 41 40 39 16 15 0
+-------------+--+--+-----+-------+--+-----+--+----+--+------------------+-----------------+
|Seg Base Addr|G |D | 0 0 |Seg Len|P | DPL |S | TYPE | Seg Base Addr | Segment Length |
+-------------+--+--+-----+-------+--+-----+--+----+--+------------------+-----------------+
G ------ 表示粒度:1=段长度为页粒度、 0=段长度为字节粒度
D ------ 缺省操作数的大小(仅在代码段描述符中识别) 1=32位段 ; 0=16位段
P ------ 该字节最高位(D7),占一位。用以确定此描述符是否有效。P=1,描述符有效;P=0,此描述符无效
DPL ---- 该字节D6, D5位,占两位。描述符所定义的段的特权级,其值为0 --- 3
S ------ 该字节D4位,占一位。S=0
TYPE---- 该字节D3,D2 ,D1,D0位,占四位。用于规定该描述符的类型:是局部描述符表描述符、调用门、任务门、中断门、自陷门中的哪一个,而其它段长,段基地址,保留字节等的定义不变。具体如下:
类型 描述 类型 描述
--------------------------------------------------
0 无用 8 无用
1 有效的286TSS 9 有效的386TSS
2 LDT A 未定义
3 286TSS忙 B 386TSS忙
4 286调用门 C 386调用门
5 任务门 D 未定义
6 286中断门 E 386中断门
7 286陷阱门 F 386陷阱门
--------------------------------------------------
--------------------------------------------------------------------
(9.1) 创建初始化任务的TSS描述符,放在GDT[4]中
P=1,描述符有效
DPL=0,
TYPE=9,有效的386TSS
Seg Base Addr = &(init_task.task.tss)
Segment Len = 104
(9.2) 创建初始化任务的LDT描述符,放在GDT[5]中
P=1,描述符有效
DPL=0,
TYPE=2,LDT
Seg Base Addr = &(init_task.task.ldt)
Segment Len = 104
(9.3) task[1...63] = NULL
GDT[6..68] = 0
(9.4) clear NT,LTS(0),LLDT(0)
(9.5) 初始化8253定时器
设定定时中断门
设定系统调用门
(10) Call buffer_init(),缓冲区初始化
在end - buffer_memory_end内,以1K大小进行分片,片头初始化
free_list组成环形链表
hash_table[0...306] = NULL
(11) Call hd_init(),硬盘驱动初始化
blk_dev[3].request_fn = DEVICE_REQUEST
挂接中断46 - hd_interrupt
复位接联的主8259A int2 的屏蔽位,允许从片发出中断请求信号。
复位硬盘的中断请求屏蔽位(在从片上),允许硬盘控制器发送中断请求信号。
(12) Call floppy_init(),软盘驱动初始话
blk_dev[2].request_fn = DEVICE_REQUEST;
挂接中断38 - floppy_interrupt
复位软盘的中断请求屏蔽位,允许软盘控制器发送中断请求信号。
(13) Call sti(),开中断
(14) Call move_to_user_mode(),进入用户模式
保存 SS, ESP, eflags, CS.
设置数据段选择子
(15) Call init()
(16) for(;;) pause();