启动linux

2019-04-14 20:58发布

<<深入分析linux内核源码>>
http://www.kerneltravel.net/kernel-book/%E6%B7%B1%E5%85%A5%E5%88%86%E6%9E%90Linux%E5%86%85%E6%A0%B8%E6%BA%90%E7%A0%81.html
13.1 初始化流程

加电或复位->bios启动->bootloader->操作系统初始化

13.1.1系统加电或复位

将内存清零,校验内存,设置CS,IP为BIOS入口FFFF:0000,启动。 bios位于rom中,不被清零。

13.1.2 BIOS启动

    主要任务:
        1.上电自检
        2.对系统内的硬件设备进行监测和连接,并把测试所得的数据存放到BIOS数据区备用
        3.读入Boot Loader
    次要任务:
        1.响应中断

13.1.3 Boot Loader

    Boot Loader通常是一段汇编代码,存放在MBR中,它的主要作用就是将系统启动代码读入内存。

13.1.4 操作系统的初始化

    完成存储管理、设备管理、文件管理、进程管理等任务的初始化,以便进入用户态。

13.3.5 LILO的运行分析
   
1.从软盘启动
    读入引导代码。
    建立栈
    建立磁盘参数表
    装入内核镜像的setup()
    装入内核其他部分
2.从硬盘启动     读入引导扇区
    建立堆栈    将第二级的引导扇区读入    读入描述符表    处理用户输入    读入操作系统初始化代码Setup.S,和内核

13.4.1 Setup.S

    检查操作系统代码
    获取和设置硬件信息
    关中断,进入保护模式
    把控制权交给Head.S这段纯32位汇编代码 13.5 main.c中的初始化

    head.s在最后部分调用main.c中的start_kernel()

start_kernel() /*定义于init/main.c */
{
……
setup_arch();
}
----------------------------------------
paging_init(); /*该函数定义于arch/i386/mm/init.c */
它的具体作用是把线性地址中尚未映射到物理地址上的部分通过页机制进行映射。
----------------------------------------
trap_init(); /*该函数在arch/i386/kernel/traps.c中定义*/
这个初始化程序是对中断向量表进行初始化
----------------------------------------
sched_init() /*在/kernel/sched.c中定义*/
仅仅为进程调度程序的执行做准备。
----------------------------------------
time_init()/*在arch/i386/kernel/time.c中定义*/
设定系统的时间----------------------------------------parse_options() /*在main.c中定义*/
这个函数把启动时得到的参数如debug,init等等从命令行的字符串中分离出来,并把这些参数赋给相应的变量。这其实是一个简单的词法分析程序。
----------------------------------------
console_init() /*在linux/drivers/char/tty_io.c中定义*/
这个函数用于对终端的初始化。在这里定义的终端并不是一个完整意义上的TTY设备,它只是一个用于打印各种系统信息和有可能发生的错误的出错信息的终端。真正的TTY设备以后还会进一步定义。
----------------------------------------kmalloc_init() /*在linux/mm/kmalloc.c中定义*/
kmalloc代表的是kernel_malloc的意思,它是用于内核的内存分配函数。而这个针对kmalloc的初始化函数用来对内存中可用内存的大小进行检查,以确定kmalloc所能分配的内存的大小。所以,这种检查只是检测当前在系统段内可分配的内存块的大小,具体内容参见第六章内存分配与回收一节。
----------------------------------------
对Linux的文件系统进行初始化
inode_init() /*在Linux/fs/inode.c中定义*/
这个函数是对VFS的索引节点管理机制进行初始化。这个函数非常简单:把用于索引节点查找的哈希表置入内存,再把指向第一个索引节点的全局变量置为空。
name_cache_init() /*在linux/fs/dcache.c中定义*/
这个函数用来对VFS的目录缓存机制进行初始化。先初始化LRU1链表,再初始化LRU2链表。
Buffer_init()/*在linux/fs/buffer.c中定义*/
这个函数用来对用于指示块缓存的buffer free list初始化。
mem_init() /* 在arch/i386/mm/init.c中定义*/
启动到了目前这种状态,只剩下运行/etc下的启动配置文件。这些文件一旦运行,启动的全过程就结束了,系统也终将进入我们所期待的用户态。

13.6.1 init进程的建立

    kernel_thread(init ,NULL,0)
   
    在调用kernel_thread(init,NULL,0)函数时,会调用main.c中的另外一个函数——init()。请注意init()函数和init进程是不同的概念。通过执行inin()函数,系统完成了下述的工作: ·建立dbflush、kswapd两个新的内核线程。 ·初始化tty1设备。该设备对应了多个终端(concole),用户登录时,就是登录在这些终端上的。 ·启动init进程。Linux首先寻找“/etc/init”文件,如果找不到,就接着找“/bin/init”文件,若仍找不到,再去找“/sbin/init”。如果仍无法找到的话,启动将无法进行下去。否则,便执行init文件,从而建立init进程。      当etc/init(假定它存在)执行时,建立好的init进程将根据启动脚本文件的内容创建其它必要的进程去完成一些重要的操作: (1) 文件系统检查。 (2) 启动系统的守护进程。 (3) 对每个联机终端建立一个“getty”进程。 (4) 执行“/etc/rc”下的命令文件。

    init 进程还负责管理系统中的“孤儿”进程

13.6.2启动所需的Shell脚本文件
    如“$HOME/profile”、“/etc/inittab”等等。
    ubuntu里已经没有inittab这个文件,改为/etc/event.d/rc-default
下面是系统的七个启动级别。     0  系统停止。如果在启动时选择该级别,系统每次运行到inittab就会自动停止,无法启动。     1  单用户模式。该模式只允许一个用户从本地计算机上登录,该模式主要用于系统管理员检查和修复系统错误。     2  多用户模式。与3级别的区别在于用于网络的时候,该模式不支持NFS(网络文件系统)。     3  完全多用户模式。可以支持Linux的所有功能,是Linux安装的默认选项。     4  未使用的模式。     5  启动后自动进入X-windwos。    6  重新启动模式。如果在启动时选择该级别,系统每次运行到inittab就会自动重新启动,无法进   入系统。
阅读(387) | 评论(0) | 转发(0) | 0 上一篇:linux内核特征 下一篇:ubuntu下使用VirtualBox 相关热门文章 给主人留下些什么吧!~~ 评论热议