1、,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,w,*,Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,www.gec-edu.org,*,Click to edit Master title style,Linux,内核基础,www.gec-edu.org,1,w,目录,认识操作系统,1,认识
2、,QT,快速入门,2,QT,进阶,信号与槽,3,2,w,不同角度看到的操作系统,操作系统,整体看,操作系统设计者,使用者,普通开发者,认识操作系统,3,w,从使用者的角度看操作系统,打开计算机,首先跳入眼帘的是什么?,要拷贝一个文件,具体的拷贝操作是谁完成的?,需要知道文件存放在何处,在硬盘的那个柱面、磁道、扇区。,数据的搬动过程怎样进行,复杂的I/O操作。,繁琐留给自己,简单留给用户,操作系统穿上华丽的外衣图形界面,操作系统穿上朴素的外衣字符界面,认识操作系统,4,w,带,系统的软件结构,应用程序,Application,设备驱动程序,Driver,硬件,(,Hardware,),应用,(,
3、Application,),标准接口函数,(,API,),操作系统,(,OS,),硬件抽象层,(,HAL,),BSP,、驱动,硬件,(,Hardware,),不带操作系统软件结构 带操作系统软件结构,两类不同的系统结构模型,5,w,从程序开发者的角度看操作系统,拷贝命令的C语言实现片断,inf=open(,“,/mnt/usbdisk/test,”,O_RDONLY,0);,outf=open(,“,/mydir/test,”,O_WRONLY,0600);,do,read_size=read(inf,buf,4096);,write(outf,buf,read_size,);,while(,
4、read_size,);,close(outf);,close(inf);,认识操作系统,6,w,从操作系统设计者的角度看操作系统,操作系统的设计目标是什么?,让各种软件资源和硬件资源高效而协调地运转起来。,尽可能地方便用户使用计算机。,假设在一台计算机上有三道程序同时运行,并试图在一台打印机上输出运算结果,必须考虑哪些问题?,从操作系统设计者的角度考虑,一个操作系统必须包含以下几部分,CPU管理,内存管理,设备管理,文件管理,认识操作系统,7,w,操作系统内核,8,w,Linux,内核,用户,程序,运行在Linux内核之上的一个庞大软件集合。,系统调用,内核的出口,用户程序通过它使用内核提供
5、的功能。,Linux内核,操作系统的灵魂,负责管理磁盘上的文件、内存,负责启动并运行程序,负责从网络上接收和发送数据包等等。,硬件,包括了Linux安装时需要的所有可能的物理设备。例如,CPU、内存、硬盘、网络硬件等等。,9,w,Linux,内核体系结构,Linux,内核采用宏内核结构(,Monolithic kernel,),所有的功能放在一个大程序中。也就是内核是,一个大程序,,是一个系统软件,管理系统的硬件资源,组织软件的工作。,庞大而复杂的核心,但是却采用子系统和分层的概念很好地进行了组织。,宏内核由于全部功能集中在一块,系统花在内核功能的切换上(例如文件系统到,IO,驱动系统上的切换
6、上)开销就非常小,提供给用户程序的反应就很快。,同时,因为全部功能集中在一块,各个功能之间的耦合度就很紧,导致了内核难以修改和增加新功能。,10,w,Linux,内核体系结构,现代的Linux内核是具有微内核特点的宏内核。,Linux,内核引入内核模块机制。通过动态加载内核模块,使得在运行过程中扩展内核的功能。不需要的时候,卸载该内核模块。,内核程序映像中包含内核的基本功能,而其他的功能可以通过内核模块的方式存在。当需要内核模块所提供的功能的支持时,再加载内核模块,把内核模块通过ld链接器链接到内核中。,11,w,Linux,内核体系结构,12,w,Linux,内核子系统,13,w,Linux
7、,内核子系统,进程调度,控制着进程对,CPU,的访问。,内存管理,允许多个进程安全地共享主内存区域,虚拟文件系统,隐藏各种不同硬供统一的接口。,网络,提供了对各种网络标准协议的存硬件的支持。,进程间通信,(IPC),支持进程间各种通信机制,包括共享内存、消息队列及管道等。,14,w,Linux,内核,的,五个子系统,1.,进程调度(,SCHED,),控制,CPU,处理进程。,当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。,可运行进程实际上是仅等待,CPU,资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。,Linux,使用了基于优先级的进程调度算法选择新的进程。,1
8、5,w,Linux,内核,的,五个子系统,2.,内存管理(,MM,),物理内存的管理:分配、释放、回收等,Linux内核采用虚拟内存技术,每个进程的虚拟内存空间为4GB。,其中0-3G属于用户空间,称为用户段,,3G-4G属于内核空间,称为内核段。,允许多个进程安全的共享主内存区域。,16,w,Linux,内核,的,五个子系统,3.,虚拟文件系统(,VirtualFileSystem,VFS,),实现了一种通用文件模型。,屏蔽了各种不同文件系统的内在差别,使得用户可以使用同样的方式访问各种不同格式的文件系统。,为用户访问不同的文件系统提供统一的通用的接口。,17,w,Linux,内核,的,五个
9、子系统,4.,网络接口(,NET,),提供了对各种网络标准的存取和各种网络硬件的支持。,网络接口可分为网络协议和网络驱动程序。,网络协议部分负责实现每一种可能的网络传输协议。,网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。,18,w,Linux,内核,的,五个子系统,5.,进程间通讯,(IPC),支持进程间各种通信机制,,包括共享内存、消息队列及管道等。,Linux的IPC是把Unix系统的进程间通讯机制移植过来的。,19,w,Linux,内核,的,五个子系统,各个子系统之间的依赖关系,处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起
10、或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程被恢复执行。例如,当一个进程通过网络发送一条消息时,网络接口需要挂起发送进程,直到硬件成功地完成消息的发送,当消息被成功的发送出去以后,网络接口给进程返回一个代码,表示操作的成功或失败。其他子系统以相似的理由依赖于进程调度。,20,w,Linux,内核,的,五个子系统,各个子系统之间的依赖关系,进程调度与内存管理之间的关系:这两个子系统互相依赖。在多道程序环境下,程序要运行必须为之创建进程,而创建进程的第一件事情,就是将程序和数据装入内存。,进程间通信与内存管理的关系:进程间通信子系统要依赖内存管理支持共享内
11、存通信机制,这种机制允许两个进程除了拥有自己的私有空间,还可以存取共同的内存区域。,虚拟文件系统与网络接口之间的关系:虚拟文件系统利用网络接口支持网络文件系统,(NFS),也利用内存管理支持,RAMDISK,设备。,内存管理与虚拟文件系统之间的关系:内存管理利用虚拟文件系统支持交换,交换进程,(swapd),定期由调度程序调度,这也是内存管理依赖于进程调度的唯一原因。当一个进程存取的内存映射被换出时,内存管理向文件系统发出请求,同时,挂起当前正在运行的进程。,21,w,Linux,的系统调用,系统调用是内核提供的一系列函数,提供给用户程序调用的一组“特殊”接口。,是应用程序和内核的交互接口。,
12、用户进程是不能存取内核使用的内存段,也不能调用内核函数。当用户进程请求内核服务时,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。,22,w,Linux,的系统调用,例如进程的创建。用户进程通过,fork、vfork创建子进程。用户进程通过系统调用fork陷入内核空间,使用内核函数do_fork和分配内核数据结构task_struct等。,23,w,Linux,的系统调用,为什么需要系统调用,出于安全的考虑。,使得用户进程不能随便的进入内核空间,访问内核变量和内核函数,。,用户进程只有只能通过系统调用获取系统内核服务,规定了用户进程进入内核的具体位置,也就是用户访问内核的路径是事
13、先规定好的,只能从规定位置进入内核,执行规定的内核函数(功能)。,24,w,Linux,的系统调用,为什么需要系统调用,用户程序通过系统调用才能够获取内核服务,是对,内核的保护,。用户进程通过系统调用,从用户态切换到内核内核,在内核态完成任务后再返回用户态。,25,Linux的系统调用,Linux的系统调用跟很多Unix和windows系统相比,简洁和高效。(Linux设计精髓),Linux系统调用继承Unix的部分系统调用(最基本和最有用的系统调用),所以Linux全部系统调用只有,30,0个左右。,按照功能大致可分为,进程控制文件系统控制,系统控制存储管理,网络管理socket控制,用户管
14、理进程间通信,使用man 2 syscalls 命令查看系统调用的说明,26,www.gec-edu.org,w,Linux的系统调用,系统调用并非直接和程序员打交道,程序员调用的是用户编程接口API。,Linux的API遵循POSIX标准,定义了一系列API,通过C库(glibc)实现。除了定义标准的C函数外,提供了一套封装例程将系统调用在用户空间封装后供用户编程使用。,27,w,Linux,内核的技术特点,Linux,内核最注重,实用和效率,。,2.6,版本前,Linux,内核是,单线程结构,非抢占的,同一时间只有一个执行线程(内核中的执行程序)允许在内核中运行,不会被调度程序打断运行其它
15、任务,这种内核被成为非抢占的。,2.6,版本后将抢占技术引入到,Linux,内核,付出的代价是同步操作进一步复杂化。,28,w,Linux,内核的技术特点,Linux内核最注重实用和效率。,内核可定制。选择适合自己的功能,将不需要的部分剔除出内核。,Linux内核对设备驱动或新文件系统等采用了,(loadable kernel module)LKM,机制,,用户在需要时可以现场动态加载,使用完毕可以动态卸载。,将模块从内核中独立出来,不必预先绑定在,kernel codes,中。这样做有三种优点:,1,将来修改,kernel,时,不必全部重新,compile,2,若需要安装新的,modules
16、,,不必重新,compile kernel,,只要插入(通过,insmode,指令)对应的,modules,3,减少内核对系统资源的占用,内核可以集中精力做最基本的事情,把一些扩展功能交由,modules,实现。,29,w,Linux,内核版本,0.01Linux(第一版),0.13版,产品化版本,实验版本 1.0.0 1.1.0(1.0.0的拷贝),1.0.X(修改),1.1.X(增加新功能,进行测试),2.4.18,2.6.,37,30,Linux内核版本,Linux,内核版本号,X.Y.Z,Y,是偶数的是稳定版,,Z,是修订号,这是,2.6,内核前的版本管理办法,在2.6稳定版的基础上增
17、加新功能和新补丁,现在一共有三个2.6版内核:第一个是稳定版内核2.6.x,由托沃兹负责维护;第二个是2.6-mm版内核,用于新技术加入稳定版前进行测试;第三个是2.6.x.y版内核(简称为.y版内核),它的用途是测试补丁。,31,www.gec-edu.org,w,内核源代码结构,32,Linux,内核源代码结构,Linux,内核源代码的结构,Linux,内核源代码位于,/usr/src/linux,目录下,/include,子目录包含了建立内核代码时所需的大部分包含文件,/init,子目录包含了内核的初始化代码,/arch,子目录包含了所有硬件结构特定的内核代码,/drivers,子目录包
18、含了内核中所有的设备驱动程序,/fs,子目录包含了所有的文件系统的代码,/net,子目录包含了内核的网络连接代码,/mm,子目录包含了所有内存管理代码,/ipc,子目录包含了进程间通信代码,/kernel,子目录包含了主内核代码,33,www.gec-edu.org,Linux,内核配置编译,编译内核的需要,Linux,作为一个自由软件,不断增加许多新的特性。想要使用这些新特性,或想,根据自己的系统度身定制一个更高效,更稳定的内核,,就需要重新编译内核。,更新的内核会支持更多的硬件,具备更好的进程管理能力,运行速度更快、更稳定,并且一般会修复老版本中发现的许多漏洞等。,34,www.gec-e
19、du.org,Linux,内核配置编译,编译内核的需要,自己定制编译的内核运行更快,系统将拥有更多的内存,不需要的功能编译进入内核可能会增加被系统攻击者利用的漏洞,将某种功能编译为模块方式会比编译到内核内的方式速度要慢一些,35,www.gec-edu.org,w,新版本内核的获取和更新,官方网站是www.kernel.org 新版本的内核的发布有两种形式,一种是full/Source版本,一般是tar.gz或者是.bz2文件。,另外一种是patch文件,即补丁。patch文件一般只有几十K到几百K,但是patch文件是针对于特定的版本的,你需要找到自己对应的版本才能使用。,例如:你有,2.6
20、.9,的源代码,但想移到,2.6.10,。就可以获得,2.6.10,的补丁文件,应用,patch,来修改,2.6.9,源文件。,$cd/usr/src/linux,$patch,pl 树状菜单。,38,w,Kbuild,构建系统,Kconfig,文件,arch/$(ARCH)/Kconfig,文件是主,Kconfig,文件,主,Kconfig,文件调用其他目录的,Kconfig,文件。,这些,Kconfig,文件形成树状关系,-,树状菜单。,script,目录下提供不同的配置工具去读取,Kconfig,文件形成不同的配置方式。如,menuconfig,目标使用,mconf,。,Document
21、ation/kbuild/kconfig-language.txt,提供了,kconfig,文件的书写语法。,39,w,Kbuild,构建系统,在,Linux,内核中增加程序的,3,项工作:,将编写的源代码复制到,Linux,内核源代码的相应目录,.,在目录的,Kconfig,文件中增加新源代码对应项目的编译配置选项,.,在目录的,Makefile,文件中增加对新源代码的编译条目,.,40,w,Kbuild,构建系统,在driverschar目录中,该目录的Kconfig文件中包含,如下,的配置项目,config,*,_RTC,bool“,*,RTC Driver”,depends on AR
22、CH_,*,help,RTC(Realtime Clock)driver for the clock inbuilt into the,*,.This can provide periodic interrupt rates from 1Hz to 64Hz for user programs,and wakeup from Alarm.,41,w,kbuild Makefile,Makefile,目标定义,目标定义用来定义哪些内容要作为模块编译,哪些要编译并连接进内核.,例如:obj-y+=foo.o,obj-y表示要由foo.c或者foo.s文件编译得到foo.o并连接进内核,obj-m表
23、示该文件要作为模块编译.,根据.config文件的CONFIG_变量来决定文件的编译方式,obj$(CONFIG_ISDN)+=isdn.o,obj$(CONFIG_ISDN_PPP_BSDCOMP)+=isdn_bsdcomp.o,42,w,Kconfig,脚本文件,多文件模块的定义,一个模块由多个文件组成,应采用模块名加,-objs,后缀或者,-y,后缀的形式来定义模块的组成文件,obj$(CONFIG_EXT2_FS)+=ext2.o,ext2-objs:=balloc.o bitmap.o,43,w,Kconfig,脚本文件,菜单项,内核配置选项对应,Kconfig,中的一个菜单项,“
24、,config”,关键字定义新的配置选项,之后的几行定义了该配置选项的属性,配置选项的属性包括类型,数据范围,输入提示,依赖关系,(,及反向依赖关系,),帮助信息和默认值等,.,每个配置选项都必须指定类型,包括,bool,,,tristate,,,string,等,config,MODVERSIONS,bool,“Set version information on all module symbols”,depends on,MODULES,help,Usually,modules have to be recompiled whenever you switch to a new kern
25、el.,44,w,Kconfig,脚本文件,菜单结构,菜单项在菜单结构中的位置定义:,menu“Network device support”,depends on NET,config NETDEVICES,.,endmenu,所有处于”,menu”,和”,endmenu”,之间的菜单项都会成为”,Network dcvice support”,的菜单项或者子菜单,.,而且,所有子菜单选项都会继承父菜单的依赖关系,45,Linux,内核配置编译,准备工作:,首先请把你需要升级的内核拷贝到/usr/src/下,#cp linux-2.6.30.tar.gz/usr/src,解压缩源代码,#ta
26、r-xzvf linux-2.6.30.tar.gz,46,www.gec-edu.org,Linux,内核配置编译,内核配置命令:,#,make config,(,基于文本的最为传统的配置界面,不推荐使用),#,make menuconfig,(基于文本菜单的配置界面,字符终端下推荐使用),#,make xconfig,(基于图形窗口模式的配置界面,,Xwindow,下推荐使用),#,make gconfig,(基于,gtk,的图形配置界面),47,www.gec-edu.org,Linux,内核配置编译,选择相应的配置时,有三种选择,它们分别代表的含义如下:,Y,-,将该功能编译进内核,N
27、,-,不将该功能编译进内核,M,-,将该功能编译成模块,可以在需要时动态插入到内核中,make xconfig,,使用鼠标就可以选择对应的选项。,make menuconfig,,则需要使用空格键进行选取。,如果有不明白的地方,按,shift+,?的组合键来查看说明,48,www.gec-edu.org,w,Linux,内核配置编译,配置的原则,大部分选项可以使用其缺省值,只有小部分需要根据用户不同的需要选择。,将与内核其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块。,有利于减小内核的长度,减小内核消耗的内存;,不需要的功能就不要选;,与内核关心紧密而且经常使用的部分功能代码直接
28、编译到内核中。,49,Linux,内核配置编译,获取硬件信息,CPU,的型号,#cat/proc/cpuinfo,输出的信息,选中对应型号的,性能有所提高。,查看,PCI,设备,lspci-v,lspci-v|grep audio,查看,USB,设备,lsusb,50,www.gec-edu.org,w,Linux,内核配置编译,配置的注意选项,Code maturity level options-,应该选择,*Prompt for development and/or incomplete code/drivers,这将会在设置界面中显示还在开发或者还没有完成的代码与驱动,.,因为有许多设
29、备可能必需选择这个选项才能进行配置,实际上它是安全的。,51,w,Linux,内核配置编译,配置的注意选项,2 General setup-,大部分保持默认,*Support for paging of anonymous memory(swap),应该选择这个选项将使你的内核支持虚拟内存。,*System V IPC,应该选择,为进程提供通信机制。有些程序只有在选,Y,的情况下才能运行,这里一定要选。,*POSIX Message Queues,POSIX,的消息队列,它同样是一种,IPC,,应该选择,*Support for hot-pluggable devices,支持热插拔的,若是为
30、普通电脑配置内核,则最好选择,52,w,Linux,内核配置编译,配置的注意选项,3 Loadable module support-,*Enable loadable module support,应该选择,这个选项可以让你的内核支持模块。一般一些不常用到的驱动或特性可以编译为模块以减少内核的体积。,*Module unloading,应该选择,这个选项可以让你卸载不再使用的模块,如果不选的话你将不能卸载任何模块,*Forced module unloading,强行卸载模块,可以把正在使用中的模快卸载掉。做内核开发或者驱动开发的时候,有一定的好处。但一般用户不应该选择。,53,w,Linu
31、x,内核配置编译,*Module versioning support,模块版本支持,该选项可以使得系统支持其它版本的内核模块。,Source checksum for all modules,否,这个功能是为了防止更改了内核模块的代码但忘记更改版本号而造成版本冲突。,*Automatic kernel module loading,在内核需要一些模块时,可以自动调用,modprobe,命令来加载需要的模块。,54,w,Linux,内核配置编译,配置的注意选项,4 Processor type and features-,Processor family(Pentium-Pro)-,选择,cp
32、u,的类型,5 Power management options(ACPI,APM)-,*Power Management support,支持高级电源管理,(,也就是平常我们说的软关机、系统休眠等,),。,55,w,Linux,内核配置编译,配置的注意选项,6 Bus options(PCI,PCMCIA,EISA,MCA,ISA)-,*PCI support PCI,支持。当然必选,PCI access mode(Any)-,PCI,的存取方式,分三种,有透过,BIOS,或是直接存取跟任意,预设值,Any,7 Executable file formats-,*Kernel support
33、 for ELF binaries,一定要选择,56,w,Linux,内核配置编译,配置的注意选项,8 Device Drivers-,Memory Technology Devices(MTD)-,存储设备层,大部分的,flash,芯片驱动都基于,MTD,。用于嵌入式系統。,Block devices,Loopback device support,可以将一个文件挂成一个文件系统。,mount iso,文件,8 file systems-,建议将根文件系统直接编译到内核中。并且在这里选择系统支持的文件系统。,57,Linux,内核配置编译,相关编译命令:,#make dep(第一次编译可忽略
34、)#make clean#make bzImage#make modules#make modules_install#make install,58,www.gec-edu.org,Linux,内核配置编译,make dep实际上读取配置过程生成的配置文件,make clean完成删除前面步骤留下的文件,make bzImage实现完全编译内核,make modules和make modules_install分别生成相应的模块和把模块拷贝到需要的目录中。,make install把生成的内核镜像拷贝到需要的目录中,并自动修改/boot/grub/grub.conf文件。,make clea
35、n,清除之前所编译的执行文件及目的文件,Make distclean,清除,所有的执行文件、目标文件,以及其他一起中间文件,只剩下源代码文件。,修改新的bootloader,用新内核启动,重新启动系统,即可引导我们新的内核。,59,www.gec-edu.org,w,启动引导器,GRUB,(,Grand Unified Boot Loader,)是个强大的启动引导器。,可对各种版本的,Linux,进行引导,,也能够正常引导其他常见的操作系统,,已经逐渐取代了,LILO,,而成为默认的启动引导器。,安装,Linux,时把,GRUB,安装到,MBR,(,Master Boot Record,主引导
36、扇区),这样主机启动时就可以自动加载启动引导器,进入,GRUB,启动菜单界面,该界面中列出了所有可被引导的操作系统。,60,w,深入分析,Linux,内核启动,61,w,62,阅读顶层目录下的Makefile,阅读顶层目录下的Makefile,找到,all和,vmlinux,w,阅读顶层目录下的,Makefile,找到vmlinux所依赖的各个文件或者目标,关于arch/x86/Makefile的引入,可以看到vmlinux包含如下内容,i386/kernel/head.S,+init/main.c+init/version.o,+CORE_FILES+DRIVERS,+NETWORKS+LI
37、BS,63,w,阅读顶层目录下的,Makefile,若make install,在i386的Makefile中有install规则,若make boot/bzImage/zImage等等,则要找到对应的目标然后进行,make boot在顶层的Makefile,中可以找到boot规则,bzImage/zImage可以在i386的,Makefile,中找到相应规则,其他的zXXX/bzXXX也都依赖于boot下的zImage/bzImage,它们最终都找到i386/boot的Makefile,64,w,65,i386/boot的Makefile,看i386/boot,的Makefile,z代表压缩
38、;b代表大内核,可见compressed下的vmlinux为,compressed/head.S+压缩后的顶层目录下的vmlinux,w,66,阅读顶层目录下的,Makefile,下面根据在bzImage/zImage中的顺序,我们依次看启动相关的源代码和相关概念,arch/i386/boot/header.S,arch/i386/boot/main.c,arch/i386/boot/compressed/head_,32,.S,arch/i386/kernel/head_,32,.S,最后进入kernel/main.C,w,67,I386机器的启动层次,BIOS(Basic I/O Syst
39、em),Boot loader,软盘启动、硬盘启动,Linux kernel,w,68,BIOS,加电,RESET引脚,初始化寄存器;CS:IP=0 xfffffff0,in ROM,ROM,BIOS,BIOS启动内容,POST(上电自检),初始化硬件设备,搜索一个操作系统来启动,根据配置,操作系统可以在软盘/硬盘/CD_ROM上,把对应设备的第一个扇区的内容(boot loader或部分)拷贝到RAM(0 x7c00)处,跳转到0 x7c00处执行,CPU加电后,将会初始化程序指针到某个约定好的地址上取指令运行,在这个地指处,往往安排了启动相关的代码,例如BIOS或者reset向量处理入口,
40、w,69,Boot loader(引导装载程序),BIOS调用Boot loader来把操作系统的内核映像装载到RAM中,考虑IBM PC的启动,软盘启动:BIOS拷贝第一个扇区的内容(bootsect)到RAM(0 x7c00)中,硬盘启动:,硬盘的第一个扇区:主引导记录MBR,Master Boot Record,MBR存储该硬盘的分区表+一小段引导程序,这个引导程序用来装载OS所在分区的第一个扇区(boot loader)的内容到RAM中,这个引导程序也可以被替换,w,70,Linux的Boot Loader,典型的有:LILO和Grub,LILO(Linux Loader),可以被安装
41、在OS分区的第一个扇区(启动扇区),也可以代替MBR中的引导程序,事实上,LILO的代码尺寸大于一个扇区,因此被分成两个部分,MBR或启动扇区部分,剩余部分,第一部分也被BIOS装载到RAM中0 x7c00的位置,第一部分在运行时将自己完整的装载到RAM中,w,71,Linux的Boot Loader,通常LILO或GRUB会显示一个已安装操作系统的列表,按照用户的选择(或者按照缺省项)装载目标操作系统运行,可能装载操作系统指定的启动代码运行,可能直接装载操作系统内核来运行,w,72,LILO的OS启动过程,显示“Loading”,header,内容被装载到RAM的0 x90000,其他操作系
42、统内核被装载到,对于小内核:0 x10000(即64K处),称为低装载,对于大内核:0 x100000(即1M处),称为高装载,跳转到setup处运行,w,73,I386内核的启动,启动方式,软盘启动:,Linux2.6.26不支持,硬盘启动:从,header的_start开始运行,在进入源代码讲解之前,我们先看一下加载i386内核的内存布局图,BIOS,LILO,Grub等boot loader,Header:_start(即0 x200偏移处),0 x7c00:,0 x90200:,w,74,硬件角度:I386实模式下的内存布局图,RAM,1-MB,ROM-BIOS,VIDEO-BIOS,
43、VRAM,0 xA0000,0 xC0000,0 xF0000,0 x00000,w,75,I386内核从实模式开始启动运行,首先看一下什么是实模式,实模式是为了兼容早期的CPU而设置的,i386系统总是始于实模式,实模式下,地址总线:20位,内存范围:01MB,逻辑地址=段地址+段内偏移,段地址=段寄存器中的值*16(或左移4位),段寄存器:cs/ds/es/fs/gs,段寄存器长度:16bit,段长:16位偏移,64KB,w,76,加载I386内核的内存布局图,zImage/Image的内核加载器所使用的经典的内存布局(1M=0 x100000),w,77,硬盘启动,两阶段引导,装载LIL
44、O,或grub,(LInuxLOader),第一个扇区,装载LINUX,header.S等,0 x90000,,其中_start在0 x90200处,系统,0 x10000,0 x100000,跳转到,_start,w,78,启动第一步,小结,总之,在跳转到,header.S的_start,的时候,内存里面的代码布局为,0 x90000:,header.S,前512字节内容,0 x90200:,header.S,的_start及其后,低装载:0 x10000:带解压的vmlinux,高装载:0 x100000:带解压的vmlinux,实模式下的内核头结构,包括,512字节的最后和_start,
45、之后的一些位置,从偏移0 x1F1开始,具体描述参见documentation/i386/boot.txt,w,79,Header.S之_start:,0 x90200,跳转到start_of_setup,检查setup的signature,清除BSS段,跳转到main执行,Main用来初始化硬件设备并为内核程序的执行建立环境,内存检测,键盘,视频,go_to_protected_mode,w,80,关于保护模式:,在setup中,从实模式,保护模式,保护模式下,地址总线32位,访存范围为4GB,原来的段寄存器现在被称作段选择子,与GDT表配合使用,GDT表由gdtr指示其位置和长度,使用特殊
46、的指令进行操作:sgdt/lgdt,w,81,图示,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,Global Descriptor,Table,GDTR,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,descriptor,Interrupt Descriptor,Tabl
47、e,IDTR,index,TI,RPL,2 1 0,15,Segment selector,线性空间,(没有开启,页表机制,时,即物,理空间),w,82,段描述符的格式,段基址、,段长度、,其他属性,w,83,一般装载gdt和idt之后,要重新装载段寄存器,cs、ds、es、fs、gs,cs通常通过一条长跳转指令装载,其他数据段寄存器直接设置,w,go_to_protected_mode,?,84,w,85,w,86,w,87,具有自解压功能的vmlinux.bin,zImage中,在0 x1000处,bzImage中,在0 x100000处,compressed/head_32.S,的sta
48、rtup_32,w,88,Compressed/head_32.S,Startup_32,初始化段寄存器和一个临时堆栈,初始化BSS段,解压缩decompress_kernel,高装载或低装载,解压缩,0 x100000(1MB),跳转到0 x100000处,linux-2.6.26archx86configsi386_defconfig中定义:,w,89,解压缩后,vmlinux在0 x100000处,根据,vmlinux.lds,,vmlinux的地址被链接为0 xc0000000+0 x100000处,如何正确运行呢?,此时仍然是实模式,还没有进入保护模式、分页、映射好,没有长跳转,只使
49、用采用相对地址的近距离跳转,w,90,Kernel/Head_32.S,Startup_32,初始化段寄存器,设置页目录和页表,分页,建立进程0的内核堆栈,Setup_idt,拷贝系统参数,识别处理器,GDT、IDT,i386_start_kernel,页目录:swapper_pg_dir,页表:pg0,?如何从08M的空间中转入3G以上的地址空间中运行的?,Kernel/head32.c,w,91,w,92,w,93,参见vmlinux_32.lds.S,arch/x86/kernel/head_32.S,w,94,关于kernel/head_32.S的内核堆栈,w,95,控制寄存器(Con
50、trol Registers),CR0,CR1,CR2,CR3,与内存相关,w,96,CR0,CR0,MSW register(Machine Status Word,32-bit version),包含系统控制位,用于控制操作模式和状态,Instruction:lmsw,LINUX setup.S,(旧版本),:,movw$1,%ax,lmsw%ax,jmp flush_instr /why?,flush_instr:,To turn on the PE-bit(enables protected-mode),PE-bit,(Protection Enabled),0,CPU is in r