linux内核初始化init(main.c)
(2014-03-27 11:19:43)
标签:
linux内核初始化main.cit |
分类: LINUX |
main.c将进行进一步初始化工作。主要方面:分配主内存功能,IDT表各中断描述符重新设定,对内核其它模块如mm,fs进行初始化,然后移到用户模式下生成进程1执行init,常驻进程0死循环执行pause。进程init加载根文件系统,设置终端标准IO,创建进程2以/etc/rc为标准输入文件执行shell.完成rc文件中的命令。
init等进程2退出,进入死循环:创建子进程,建立新会话,设置标准IO终端,以登录方式执行shell.
至此系统动作起来了。
所以整个系统的建立起来后除了两个死循环的进程idle和init,其它的动作都是由用户在shell下执行命令,产生系统调用来工作的。
通过执行move_to_usermdoe(),idle和init进程都属于用户态下的进程。而内核则完全是中断驱动的。也就是说只有通过中断才能进入系统,如时钟和系统调用等。
所以问题的重点就在于内核各部分数据结构的建立、初始化、操作是怎样进行的。这些初始化流程涉及到内核各个模块全部重要的数据结构。
现在从main执行的一系列初始化代码来浅窥一下:
1.根据内存的大小,设置高速缓冲的末端。16M内存把高速缓冲末端设为4M。缓冲末端到主存末端为主内存区。
2.mem_init(main_memory_start,memory_end);主内存区初始化
3.trap_init().硬件中断向量表设置。
4.blk_dev_init();
5.chr_dev_init();
6.tty_init();
7.time_init().取CMOS 时钟,并设置开机时间 startup_time(为从1970-1-1-0 时起到开机时的秒数)
8.sched_init(); // 调度程序初始化(加载了任务0 的tr, ldtr)
lldt
(0);
设置内核的工作心跳--8253定时器,安装定时器中断。
设置系统调用中断门:set_system_gate (0x80, &system_call);
9.buffer_init(buffer_memory_end);// 缓冲管理初始化,建内存链表等。
10.hd_init();// 硬盘初始化。
11.floppy_init();//软盘初始化。
12.sti()开中断。
13.move_to_user_mode();移动到用户态执行。
这是个宏。由嵌入汇编代码组成。设置内核堆栈中的CS为任务0代码段(用户态),通过中断返回iret, 自动加载了LDT0的代码段到CS,数据段到SS,DS等,完成了从特权级从0跳到3。其实执行的代码在内存中的位置完全相同。只是完成执行权跳到用户态而已。这样,内核执行变成了任务0的执行。
14.fork();生成进程1,执行init();
这里的fork()是内联函数。为了不使用用户栈。
进程0从此死循环执行pause();
15 init();
进程1执行init()函数。
调用setup取硬盘分区信息hd.加载虚拟盘,进程init加载根文件系统,设置终端标准IO,创建进程2以/etc/rc为标准输入文件执行shell.完成rc文件中的命令。加载完根文件系统之后,整个OS就已经完整地运行起来了。
init等进程2退出,进入死循环:创建子进程,建立新会话,设置标准IO终端,以登录方式执行shell.,剩下的动作由用户来决定了。

加载中…