资源描述
,Click to edit Master title style,Click to edit Master text styles,Click to edit Master title style,Click to edit Master text styles,Click to edit Master title style,Click to edit Master text styles,第,1,章,Linux,内核介绍,在进行系统移植的时候,移植的核心就是内核的移植。内核移植的不仅影响到系统的功能,而且还影响到整个系统的性能。因此,了解,Linux,内核,有利于开发人员进行系统裁剪和移植。下面主要针对,Linux,内的五个重要部分系统调用接口、进程管理、内存管理、虚拟文件系统和设备驱动程序,进行介绍。,1.1,系统调用接口,系统调用是操作系统提供给用户程序调用的一组“特殊”接口。用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。例如,用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件;通过时钟相关的系统调用获得系统时间或设置系统时间;通过进程控制相关的系统调用来创建进程、实现进程调度、进程管理等。,1.1.1 Linux,系统调用,所有的操作系统在内核里都有一些内建的函数,这些函数完成对硬件的访问和对文件的打开、读、写、关闭等操作。,Linux,系统中称这些函数叫做“系统调用”(即,systemcall,)。这些函数实现了将操作从用户空间转换到内核空间,有了这些接口函数,用户就可以方便地访问硬件。例如,在用户空间调用,open(),函数,则会在内核空间调用,sys_open(),。一个已经安装的系统所支持的系统都调用可以在,/usr/include/bits/syscall.h,文件里面看到。,1.1.2,用户编程接口,用户编程接口是为用户编程过程提供的各种功能库函数,如分配空间、拷贝字符、打开文件等。,Linux,用户编程接口(,API,)遵循了在,UNIX,中最流行的应用编程界面标准,POSIX,标准。它与系统调用之间存在一定的联系和区别。不同的语言和平台为用户提供了丰富的编程接口,包括网络编程接口、图形编程接口、数据库编程接口等,但这些不是系统调用。,1.1.3,系统调用与服务例程的对应关系,为了通过系统调用号来调用不同的内核服务例程,系统必须创建并管理好一张系统调用表。该表用于将系统调用号与内核服务函数的映射。,Linux,是用数组,sys_call_table,来表示这个表。在这个表的每个表项中存放着对应内核服务例程的指针,而该表项的下标就是该内核服务例程的系统调用号。,Linux,规定,在,I386,体系中,处理器的寄存器,eax,用来传递系统调用号。,1.1.4,系统调用过程,通常情况下,abc(),系统调用对应的服务例程的名字是,sys_abc(),。,(,1,)用户程序中调用库函数,abc(),。,(,2,)系统加载,libc,库调用索引和参数后,执行,int $0x80,或者,sysenter,汇编指令进入系统调用,执行,system_call,函数。,(,3,),system_call,函数根据传递过来的参数处理所有的系统调用。使用,system_call_table,参数,执行系统调用。,(,4,)系统调用返回。,(,5,)执行,iret,或者,sysexit,汇编指令两种方式退出系统调用,并调用,resume_userspace,进入用户空间。,(,6,)继续在,libc,库中执行,执行完成后返回到用户应用程序中。,1.1.5,系统调用传递的参数,系统调用中输入输出的参数为实际传递的值或者是用户态进程的地址,或者是指向用户态函数的指针的数据结构地址。传递的参数放在寄存器,eax,中,即系统调用号。寄存器传递参数的个数满足两个条件:,参数的长度不超过寄存器的长度,如果是,32,位平台不 超过,32,位,,64,位平台不超过,64,位。,不包括,eax,中的系统调用号,参数的个数不超过,6,个。,1.2,进程管理,进程管理包括创建进程、管理进程以及删除进程。进程管理是,Linux,内核的重要部分,对系统的核心资源进行管理。做好系统移植需要对这部分知识有一定的了解。,1.2.1,进程,进程是程序执行时的一个实体。程序包含指令和数据,而进程包含程序计数器和全部,CPU,寄存器的值。进程的堆栈中存储着一些数据,如子程序参数、返回地址以及变量之类的临时数据。当前的执行程序(进程)包含着当前处理器中的活动状态。,1.2.2,进程描述符,内核对进程的优先级、进程的状态、地址空间等采用进程描述符表示。在,Linux,内核内,进程是由相当大的一个称为,task_struct,的结构表示。,state,:表示进程的状态,,-1,代表“不能运行”,,0,代表“运行”,,0,代表“停止”。,flags,:定义了很多指示符,表明进程是否正在被创建(,PF_STARTING,)或退出(,PF_EXITING,),或是进程当前是否在分配内存(,PF_MEMALLOC,)。可执行程序的名称(不包含路径)占用,comm,(命令)字段。,tasks,字段提供了链接列表的能力。它包含一个,prev,指针(指向前一个任务)和一个,next,指针(指向下一个任务)。,1.2.3,进程状态,进程描述符中,state,字段描述进程当前的状态。它由一组标志组成,其中每个标志描述一种可能的进程状态。下面分别对这些状态进行描述:,可运行状态:进程处于运行(它是系统的当前进程)或者准备运行状态(它在等待系统将,CPU,分配给它)。,等待状态:进程在等待一个事件或者资源。,Linux,将等待进程分成两类;可中断的等待状态与不可中断的等待状态。可中断等待进程可以被信号中断;不可中断等待进程直接在硬件条件等待,并且任何情况下都不可中断。,暂停状态:进程被暂停,通常是通过接收一个信号。正在被调试的进程可能处于停止状态。,僵死状态:进程的执行被终止,但是,父进程还没有发布,wait4(),或,waitpid(),系统调用来返回有关死亡进程的信息。,1.2.4,进程调度,Linux,进程调度的目的就是调度程序运行时,要在所有可运行状态的进程中选择最值得运行的进程投入运行。每个进程的,task_struct,结构中有以下四项,policy,、,priority,、,counter,、,rt_priority,。这四项是选择进程的依据。,1.2.5,进程地址空间,Linux,的虚拟地址空间为,0,4G,字节。虚拟的,4G,字节空间被,Linux,内核分为内核空间和用户空间两部分。将最高的,1G,字节(从虚拟地址,0xC0000000,到,0xFFFFFFFF,),留给内核使用,称为“内核空间”。将较低的,3G,字节(从虚拟地址,0x00000000,到,0xBFFFFFFF,),留给用户进程使用,称为“用户空间”。因为每个进程可以通过系统调用进入内核,因此,,Linux,内核空间被系统的所有进程共享,实际上对于某个进程来说,它仍然可以拥有,4G,字节的虚拟空间。,1.3,内存管理,RAM,的一部分被静态地划分给了内核,用来存放内核代码和静态数据结构。,RAM,的其余部分称为动态内存(,dynamic memory,),这不仅是运行用户进程所需的宝贵资源,也是内核所需的宝贵资源。事实上,整个系统的性能取决于如何有效地管理动态内存。,1.3.1,内存管理技术,页表(,page tables,):进程在读取指令和存取数据时都要访问内存。在一个虚拟内存系统中,所有的地址都是虚拟地址而非物理地址。操作系统维护虚拟地址和物理地址转换的信息,处理器通过这组信息将虚拟地址转换为物理地址。虚拟内存和物理内存被分为适当大小的块,叫做页。为了将虚拟地址转换为物理地址,首先,处理器要找到虚拟地址的页编号和页内偏移量;然后,处理器根据虚拟地址和物理地址的映射关系将虚拟页编号转换为物理的页;最后,根据偏移量访问物理页的确定偏移位置。每个物理页面都有一个,struct page,结构,位于,include/linux/mm.h,,该结构体包含了管理物理页面时的所有信息。,1.3.2,内存区管理,内存区(,memory area,)是具有连续的物理地址和任意长度的内存单元序列。伙伴系统采用的是页框作为基本内存区,适合于大内存的请求,对小内存的请求容易造成内碎片。为了解决内碎片的问题,将内存区大小按几何分布划分,也就是将内存区划分成,2,的幂的大小。不论请求的大小为多大时,总能保证内碎片小于内存区的,50%,。为此,内核建立了,13,个按几何分布的空闲内存区链表,大小从,32,字节到,131072,字节。伙伴系统的调用为了获得存放新内存区所需的额外页框,同时也为了释放不再包含内存区的页框。,1.3.3,内核中获取内存的几种方式,操作系统的内存管理方案优劣是决定其效率高低的重要因素,时间与空间的常常作为内存管理方案优劣的衡量指标。首先,分配,/,释放内存是一个发生频率很高的操作,所以它要求有一定的实时性,另外,内存又是一种非常宝贵的资源,.,所以要尽量减少内存碎片的产生。,1.4,虚拟文件系统,虚拟文件系统的思想是把不同种类的文件系统的共同信息放入内核。其中一个字段或函数来支持,Linux,所支持的各种文件系统提供的操作。对所调用的读、写或其他函数,内核都能把它们替换成支持,Linux,文件系统、,NFS,文件系统,或者其他文件系统的实际函数。在第,2,章中,会讲到,Linux,的安装,在虚拟机上安装,Linux,,同时实现,Linux,和,Windows,实现文件共享。就是实现在,Linux,环境下能够直接访问,Windows,的,FAT32,文件系统。,1.4.1,虚拟文件系统作用,虚拟文件系统(,Virtual Filesystem,),实际上是对各种文件系统的一种封装,为各种文件系统提供了一个通用的接口。通常情况下,为了实现不同操作系统下文件访问,例如拷贝,/usr/local/arm,目录下,zImage,文件到,/mnt/hgfs/Windows,目录下。,VFS,支持的文件系统可分为以下三个主要的类型。,1,磁盘文件系统,2,网络文件系统(,NFS,),3,特殊文件系统,1.4.2,文件系统的注册,每个注册的文件系统是指可能会被挂载到目录树中的各个实际文件系统。实际文件系统,即指,VFS,中的实际操作最终要通过它们来完成而已,并不表示它们必须要存在于特定的某种存储设备上。,name,:文件系统名,如,ext2,fs_flags,:文件系统类型标志,get_sb,:读超级块的方法,kill_sb,:删除超级块的方法,owner,:指向实现文件的模块的文件的指针,next,:指向文件系统类型链表中下一个文件系统的指针,fs_supers,:具有相同文件系统类型的超级块对象链表的头,1.4.3,文件系统的安装和卸载,在,Linux,系统中,同一个文件系统可以被多次安装。一个文件系统被安装多次,那么就可以通过这多个安装点来访问。尽管可以通过这多个安装点来访问,但是文件系统却只有一个。不管文件系统被安装了多少次,都只有一个超级块对象。,1.5,设备驱动程序,设备驱动,实际上是硬件功能的一个抽象。针对同一个硬件不同的驱动可以将硬件封装成不同的功能。设备驱动是硬件层和应用程序(或者操作系统)的媒介,能够让应用程序或者操作系统能够使用硬件。在,Linux,操作系统下有,3,类主要的设备文件类型:块设备、字符设备和网络设备。设备驱动程序是指管理某个外围设备的一段代码,它负责传送数据、控制特定类型的物理设备的操作,包括开始和完成,IO,操作,检测和处理设备出现的错误。,1.5.1,字符设备驱动程序,字符设备是一种能像字节流一样进行串行访问的设备,对设备的存取只能按顺序按字节存取而不能随机访问,字符设备没有请求缓冲区,必须按顺序执行所有的访问请求。应用程序对字符设备的访问是通过字符设备节点来完成的。字符设备是,Linux,中最简单的设备,可以像文件一样访问。应用程序使用标准系统调用打开、读、写和关闭字符设备,完全可以把它们当作普通文件一样进行操作。甚至正在被,PPP,守护进程使用,用于将一个,Linux,系统连接到网上的,modem,,也被看作一个普通文件。,1.5.2,块设备驱动程序,块设备具有请求缓冲区,从块设备读取数据时,可以从任意位置读取任意长度,即块设备支持随机访问而不必按照顺序存取数据。例如,可以先存取后面的数据,然后再存取前面的数据,字符设备则不能采用该方式存取数据。,Linux,下的磁盘设备均为块设备,应用程序访问,Linux,下有块设备节点是通过文件系统及其高速缓存来访问块设备的,并非直接通过设备节点来读写块设备上的数据。,1.5.3,网络设备驱动程序,网络设备与字符设备的区别是,网络设备是面向数据报文的,而字符设备是面向字符流的。网络设备与块设备的区别是,网络设备不支持随机访问,也没有请求缓冲区。在,Linux,里网络设备也可以被称为网络接口,如,eth0,,应用程序是通过,Socket,(套接字),而不是设备节点来访问网络设备,在系统中不存在网络设备节点。,1.5.4,内存与,I/O,操作,一般来说,在系统运行时,外设的,I/O,内存资源的物理地址是已知的,由硬件的设计决定。但是,CPU,通常并没有为这些已知的外设,I/O,内存资源的物理地址预定义虚拟地址范围,驱动程序并不能直接通过物理地址访问,I/O,内存资源,只能先将它们映射到内核的虚拟地址空间内(通过页表),然后才能根据映射的内核虚拟地址范围,通过访内指令访问这些,I/O,内存资源。,Linux,在,io.h,头文件中声明了函数,ioremap(),,用来将,I/O,内存资源的物理地址映射到核心虚地址空间(,3GB,4GB,)中。,1.6,小结,Linux,内核是一个比较庞大的系统,深入理解内核可以减少在系统移植中的障碍。在系统移植中设备驱动开发是一项很复杂的工作,由于,Linux,内核提供了相当部分的源代码,同时还提供了对某些公共部分的支持。例如,在,USB,驱动对读写,U,盘、键盘、鼠标等设备提供了通用驱动程序。一般情况可以直接使用内核提供的驱动,通过修改相似的驱动程序。但是对于复杂的,USB,设备没有现成的驱动,就需要对驱动开发过程有一定的认识,参考,Linux,源码进行重新开发驱动。,
展开阅读全文