1.Linux内核在整个计算机系统中的位置 图1-计算机系统层次结构自上而下:靠近顶部的层依赖于较低层,但靠近底部的子系统不依赖于较高层。子系统依赖于底层的子系统,反之则不然。 2.内核的作用 1.虚拟化(抽象),将计算机硬件抽象成虚拟机,供用户进程进程使用;进程在运行时,不需要知道硬件是如何工作的,只要调用Linux内核提供的virtualinterface虚拟接口就够了。 2。多任务处理实际上是并行使用计算机硬件资源的多个任务。内核的任务是仲裁资源的使用,造成每个进程都认为自己是独占系统的错觉。(通过task_struct的文件可以找到),进程内存的执行空间已经被替换(通过task_struct的mem可以找到)。 3。Linux内核整体架构 Linux内核整体架构 中央系统是进程调度器ProcessScheduler,SCHED:其他所有子系统都依赖于进程调度器,因为其余的子系统都是进程需要被阻止和恢复。当进程需要等待硬件动作完成时,对应的子系统就会阻塞进程;当硬件动作完成后,子系统将恢复进程:阻塞和恢复动作都依赖于进程调度器来完成。 上图中每个依赖箭头都有一个原因: ◆进程调度器依赖于内存管理器内存管理器:当进程恢复执行时,需要依赖内存管理器为其运行分配内存. ◆IPC子系统依赖于内存管理器:共享内存机制是一种进程间通信的方式,运行两个进程使用相同的共享内存空间进行信息传递。 ◆VFS依赖网络接口NetworkInterface:支持NFS网络文件系统; ◆VFS依赖于内存管理器:支持ramdisk设备 ◆内存管理器依赖于VFS,因为需要支持swapping,可以将暂时不运行的进程换出到磁盘上的swap分区,并进入暂停状态。 4。高度模块化的设计系统有利于分工协作 只有极少数程序员需要跨多个模块工作。系统时间。 四个模块的可扩展性:硬件设备驱动、文件系统模块、逻辑文件系统模块、网络设备驱动、网络协议模块。 5.系统中的数据结构 1。任务列表TaskList 进程调度器为每个进程维护一个数据结构task_struct;所有进程由一个链表管理,形成一个任务列表;进程调度器还维护了一个当前指针,指向当前占用CPU的进程。 2。MemoryMappingMemoryMap 内存管理器存储了每个进程从虚拟地址到物理地址的映射;并且还提供了如何换出特定页面,或如何处理页面错误。这些信息存储在数据结构mm_struct中。每个进程都有一个mm_struct结构,在进程的task_struct结构中,有一个指针mm指向二级进程的mm_struct结构。 mm_struct中有一个指针pgd,指向进程的页目录表(即存放页目录首地址)-->当进程被调度时,这个指针被替换为一个物理地址并写入控制寄存器CR3(x86架构下的页基址寄存器)。 3.I-nodes VFS通过inodes节点表示文件在磁盘上的映像,inode用来记录文件的物理属性。每个进程都有一个files_struct结构,用来表示进程打开的文件,task_struct中有一个files指针。使用inode节点可以进行文件共享。共享文件有两种方式:(1)通过同一个系统打开文件,指向同一个inodes节点,发生在父子进程之间;(2)通过不同系统打开文件指向同一个inode节点,比如有硬链接;或两个不相关的指针打开同一个文件。 4。DataConnectionDataConnection 内核中所有数据结构的根都在进程调度器维护的任务列表列表中。在系统中每个进程的数据结构task_struct中,都有一个指针mm指向它的内存映射信息;还有一个指针files指向它打开的文件(用户打开文件表);还有一个指针指向进程Character打开的网络套接字。#p# 6.子系统架构 1。ProcessScheduler进程调度器架构 (一)目标 进程调度器是Linux内核中最重要的子系统。它被系统用来控制对CPU的访问——不仅是用户进程对CPU的访问,还有其他子系统对CPU的访问。(2)模块 进程调度器 调度策略模块调度策略模块:决定哪个进程获得CPU的访问权;调度策略应该允许所有进程尽可能公平地共享CPU。 ◆架构专用模块设计一套统一的抽象接口,屏蔽特定架构接口芯片的硬件细节。该模块与CPU交互以阻止和恢复进程。这些操作包括获取每个进程需要保存的寄存器和状态信息,执行汇编代码完成阻塞或恢复操作。 ◆架构无关模块架构无关模块与调度策略模块交互决定下一个执行流程,然后调用架构无关代码恢复该流程的执行。不仅如此,该模块还调用内存管理器接口,确保被阻塞进程的内存映射信息被正确保存。 ◆系统调用接口模块系统调用接口允许用户进程访问Linux内核显式暴露给用户进程的资源。通过一组定义明确的基本不变的接口(POSIX标准)将用户应用程序与Linux内核解耦,从而使用户进程不会受到内核变化的影响。 (3)数据表示 调度器维护一个数据结构——任务列表,其元素是每个活跃进程的task_struct实例;这个数据结构不仅包含用于阻塞和恢复进程的信息,还包含额外的计数和状态信息。该数据结构可在整个内核层中公开访问。 (4)依赖、数据流、控制流 上文提到,调度器需要调用内存管理器提供的函数,为需要恢复执行的进程选择合适的物理地址,正是因为因此,进程调度器子系统依赖于内存管理子系统。当其他内核子系统需要等待硬件请求完成时,它们都依赖于进程调度子系统来阻塞和恢复进程。这种依赖性通过函数调用和对共享任务列表数据结构的访问来体现。所有内核子系统都读取或写入表示当前正在运行的进程的数据结构,从而形成贯穿整个系统的双向数据流。 除了内核层的数据流和控制流,OS服务层还提供了为用户进程注册定时器的接口。这形成了调度程序对用户进程的控制流。通常唤醒休眠进程的用例不在正常控制流的范围内,因为用户进程无法预测它何时会被唤醒。最后,调度器与CPU交互,阻塞和恢复进程,进而形成它们之间的数据流和控制流——CPU负责中断当前正在运行的进程,让内核调度其他进程运行。 2。内存管理器内存管理器架构 (一)目标 内存管理模块负责控制进程如何访问物理内存资源。进程虚拟内存和机器物理内存之间的映射由硬件内存管理系统(MMU)管理。每个进程都有自己独立的虚拟内存空间,所以两个进程可能有相同的虚拟地址,但实际上它们运行在不同的物理内存区域。MMU提供内存保护,使两个进程的物理内存空间不互相干扰。内存管理模块还支持交换——将暂时不用的内存页换出到磁盘上的交换分区。该技术使进程的虚拟地址空间大于物理内存的大小。虚拟地址空间的大小由机器字大小决定。 (2)模块 内存管理子系统 ◆架构相关模块架构具体模块提供访问物理内存的虚拟接口。 ◆架构无关模块架构无关模块负责各个进程的地址映射和虚拟内存交换。当发生页面错误时,该模块负责决定将哪个内存页面换出内存——因为这种内存页面交换选择算法几乎不需要改变,所以这里没有建立独立的策略模块。 ◆系统调用接口系统调用接口为用户进程提供了严格的访问接口(malloc和free;mmap和ummap)。该模块允许进程分配和释放内存,并执行内存映射文件操作。 (3)数据表明 内存管理存储了每个进程从虚拟内存到物理内存的映射信息。这个映射信息保存在mm_struct结构实例中,指向这个实例的指针保存在每个进程的task_struct中。除了存储映射信息外,数据块还应该存储有关内存管理器如何获取和存储页面的信息。例如:可执行代码可以存储可执行映像作为备份;但是,动态请求的数据必须备份到系统页面。(这个我没看懂,求助?) ***,内存管理模块还应该存储访问和技术信息,以保证系统的安全。 (4)依赖、数据流和控制流 内存管理器控制着物理内存。当页面错误发生时,它接受来自硬件的通知(页面错误中断)——这意味着内存管理模块内存管理硬件和内存管理硬件之间存在双向数据流和控制流。内存管理也依赖于文件系统来支持交换和内存映射I/O——这个需求意味着内存管理器需要调用文件系统提供的函数接口过程调用来将内存页面存储在磁盘上并从中获取内存页面磁盘。因为文件系统请求很慢,内存管理器使得进程在等待内存页被换入之前需要进入休眠——这个要求使得内存管理器调用进程调度器的接口。由于每个进程的内存映射存储在进程调度器的数据结构中,内存管理器和进程调度器之间也存在双向的数据流和控制流。用户进程可以创建新的进程地址空间并知道页面错误——这需要来自内存管理器的控制流。一般来说,用户进程没有数据流向内存管理器,但是用户进程可以通过select系统调用从内存管理器获取一些信息。#p# 3。虚拟文件系统架构 (1)目标 虚拟文件系统为存储在硬件设备上的数据提供统一的访问接口。兼容不同的文件系统(ext2、ext4、ntf等)。计算机中几乎所有的硬件设备都由一个通用的设备驱动程序接口表示。逻辑文件系统有助于与其他操作系统标准兼容,并允许开发人员使用不同的策略来实现文件系统。虚拟文件系统更进一步,允许系统管理员在任何设备上安装任何逻辑文件系统。虚拟文件系统封装了物理设备和逻辑文件系统的细节,允许用户进程使用统一的接口访问文件。 除了传统的文件系统目标,VFS还负责加载新的可执行文件。该任务由逻辑文件系统模块执行,它使Linux能够支持多种可执行文件。 (2)模块 虚拟文件系统模块 ◆设备驱动模块 ◆设备独立接口模块DeviceIndependentInterface:提供所有设备的相同视图。 ◆逻辑文件系统逻辑文件系统:针对每个支持的文件系统。 ◆系统独立接口系统独立接口提供了一个与硬件资源和逻辑文件系统无关的接口。该模块通过块设备节点或字符设备节点提供所有资源。 ◆系统调用模块系统调用接口,为用户进程提供对文件系统的统一控制访问。虚拟文件系统屏蔽了用户进程的所有特殊功能。 (3)数据表示 所有文件都用inode表示。每个inode记录了一个文件在硬件设备上的位置信息。不仅如此,inode还存储了指向逻辑文件系统模块和设备驱动程序的函数指针,可以执行特定的读写操作。通过以这种形式存储函数指针(即面向对象中虚函数的思想),特定的逻辑文件系统和设备驱动程序可以向内核注册自己,而不需要内核依赖特定的模块特性。 (4)依赖关系、数据流和控制流 一个特殊的设备驱动程序是ramdisk,它在主内存中分配一块区域并将其用作持久存储设备。这个设备驱动使用内存管理模块来完成任务,所以VFS和内存管理模块之间存在依赖关系(图中的依赖是反的,应该是VFS依赖内存管理模块),数据流和控制流。 逻辑文件系统支持网络文件系统。此文件系统从另一台机器访问文件,就好像它们是本地文件一样。为实现此功能,逻辑文件系统通过网络子系统完成其任务——这引入了VFS对网络子系统的依赖性以及它们之间的控制和数据流。 如前所述,内存管理器将VFS用于内存交换功能和内存映射I/O。另外,当VFS等待硬件请求完成时,VFS需要使用进程调度器来阻塞进程;当请求完成后,VFS需要通过进程调度器唤醒进程。***,系统调用接口允许用户进程调用访问数据。与之前的子系统不同,VFS不提供用户注册模糊调用的机制,因此不存在从VFS到用户进程的控制流。 4。网络接口网络接口架构 (一)目标 网络子系统使Linux系统能够通过网络连接到其他系统。该子系统支持多种硬件设备和多种网络协议。网络子系统屏蔽了硬件和协议的实现细节,抽象出一个简单易用的接口供用户进程和其他子系统使用——用户进程和其他子系统不需要知道硬件设备和协议的细节。 (2)模块 网络协议层模块图 ◆网络设备驱动 ◆设备独立接口模块设备独立接口模块为所有硬件设备提供一致的访问接口,使得系统的高层不需要知道硬件的细节。 ◆网络协议模块网络协议模块负责实现各个网络传输协议,如:TCP、UDP、IP、HTTP、ARP等~ ◆协议独立接口提供对特定协议和特定硬件的独立性设备的一致接口。这允许其余的内核子系统无需依赖特定协议或设备即可访问网络。 ◆系统调用接口模块系统调用接口规定了用户进程可以访问的网络编程API。(3)数据表示 每个网络对象都表示为一个socket套接字。套接字与进程相关联的方式与inode节点相同。套接字可以通过两个指向同一个套接字的task_structs被多个进程共享。 (4)数据流、控制流和依赖 当网络子系统需要等待硬件请求完成时,需要通过进程调度系统阻塞和唤醒进程——这样就形成了网络子系统和进程调度子系统之间的控制流和数据流。不仅如此,虚拟文件??系统通过网络子系统实现了网络文件系统(NFS)——这就形成了VFS和网络子系统钉钉的数据流和控制流。 7。结语 1。Linux内核是整个Linux系统中的一层。从概念上讲,内核由五个主要子系统组成:进程调度程序模块、内存管理模块、虚拟文件系统、网络接口模块和进程间通信模块。这些模块通过函数调用和共享数据结构交换数据。 2。Linux内核架构为他的成功做出了贡献。这种架构让大量的志愿开发者能够适当的分工合作,使得各个具体的模块易于扩展。 ◆可扩展性1:Linux架构通过数据抽象技术使这些子系统具有可扩展性——每个具体的硬件设备驱动程序都实现为一个单独的模块,支持内核提供的统一接口。通过这种方式,各个开发人员可以将新的设备驱动程序添加到Linux内核中,而与其他内核开发人员的交互最少。 ◆可扩展性2:Linux内核支持多种不同的架构。在每个子系统中,架构相关的代码被分离出来,形成一个单独的模块。这样,当一些厂商推出自己的芯片时,他们的内核开发团队只需要在内核中重新实现机器相关的代码,就可以将内核移植到新的芯片上运行。参考文章:1.http://oss.org.cn/ossdocs/linux/kernel/a1/index.html2.http://www.cs.cmu.edu/afs/cs/project/able/www/paper_abstracts/intro_softarch.html3.http://www.cs.cmu.edu/afs/cs/project/able/www/paper_abstracts/intro_softarch.html4.http://www.fceia.unr.edu.ar/ingsoft/梦露00.pdf5.内核源码:http://lxr.oss.org.cn/
