Linuxkernel成功的两个诱因:
灵活的构架设计致使大量的志愿开发者就能很容易加入到开发过程中;
每位子系统(尤其是这些须要改进的)都具备良好的可扩充性。
正是这两个诱因促使Linuxkernel可以不断进化和改进。
一、Linux内核在整个计算机系统中的位置
分层结构的原则:
thedependenciesbetweensubsystemsarefromthetopdown:layerspicturednearthetopdependonlowerlayers,butsubsystemsnearerthebottomdonotdependonhigherlayers.
这些子系统之间的依赖性只能是从上到下,也就是图中底部的子系统依赖顶部的子系统,反之则不行。
二、内核的作用
虚拟化(具象),将计算机硬件具象为一台虚拟机,供用户进程process使用;进程运行时完全不须要晓得硬件是怎样工作的,只要调用Linuxkernel提供的虚拟插口virtualinterface即可。
多任务处理,实际上是多个任务在并行使用计算机硬件资源,内核的任务是仲裁对资源的使用,制造每位进程都以为自己是独占系统的错觉。
PS:进程上下文切换就是要换掉程序状态字、换掉页表基地址寄存器的内容、换掉current指向的task_struct实例、换掉PC——>也就换掉了进程打开的文件(通过task_struct的files可以找到)、换掉了进程显存的执行空间(通过task_struct的mem可以找到);
三、Linux内核的整体构架
中心系统是进程调度器ProcessScheduler,SCHED:所有其余的子系统都依赖于进程调度器,由于其余子系统都须要阻塞和恢复进程。当一个进程须要等待一个硬件动作完成时,相应子系统会阻塞这个进程;当这个硬件动作完成时,子系统会将这个进程恢复:这个阻塞和恢复动作都要依赖于进程调度器完成。
上图中的每一个依赖箭头都有缘由:
进程调度器依赖显存管理器Memorymanager:进程恢复执行时,须要借助显存管理器分配供它运行的显存。
IPC子系统依赖于显存管理器:共享显存机制是进程间通讯的一种方式,运行两个进程借助同一块共享的显存空间进行信息传递。
VFS依赖于网路插口NetworkInterface:支持NFS网路文件系统;
VFS依赖于显存管理器:支持ramdisk设备
显存管理器依赖于VFS,由于要支持交换swapping,可以将暂时不运行的进程换出到c盘上的交换分区swap,步入挂起状态。
四、高度模块化设计的系统,利于分工合作。
只有极少数的程序员须要横越多个模块举办工作,这些情况确实会发生,仅发生在当前系统须要依赖另一个子系统时;
硬件设备驱动hardwaredevicedrivers、文件系统模块logicalfilesystemmodules、网络设备驱动networkdevicedrivers和网路合同模块networkprotocolmodules这四个模块的可扩充性最高。
五、系统中的数据结构
任务列表TaskList
进程调度器针对每位进程维护一个数据结构task_struct;所有的进程用数组管理,产生tasklist;进程调度器还维护一个current表针指向当前正在占用CPU的进程。
显存映射MemoryMap
显存管理器储存每位进程的虚拟地址到化学地址的映射;而且也提供了怎么换出特定的页,或则是怎样进行缺页处理。这种信息储存在数据结构mm_struct中。每位进程都有一个mm_struct结构,在进程的task_struct结构中有一个表针mm指向次进程的mm_struct结构。
在mm_struct中有一个表针pgd,指向该进程的页目录表(即储存页目录首地址)——>当该进程被调度时,此表针被换成数学地址,写入控制寄存器CR3(x86体系结构下的页基址寄存器)
I-nodes
VFS通过inodes节点表示c盘上的文件镜像linux内核探秘:深入解析文件系统和设备驱动的架构与设计,inodes用于记录文件的化学属性。每位进程都有一个files_struct结构,用于表示该进程打开的文件,在task_struct中有个files表针。使用inodes节点可以实现文件共享。文件共享有两种形式:(1)通过同一个系统打开文件file指向同一个inodes节点,这些情况发生于兄妹进程间;(2)通过不同系统打开文件指向同一个inode节点,举例有硬链接;或则是两个不相关的表针打开同一个文件。
数据联接DataConnection
内核中所有的数据结构的根都在进程调度器维护的任务列表数组中。系统中每位进程的的数据结构task_struct中有一个表针mm指向它的显存映射信息;也有一个表针files指向它打开的文件(用户打开文件表);还有一个表针指向该进程打开的网路套接字。
六、子系统构架
1.进程调度器ProcessScheduler构架
(1)目标
进程调度器是Linuxkernel中最重要的子系统。系统通过它来控制对CPU的访问——不仅仅是用户进程对CPU的访问,也包括其余子系统对CPU的访问。
(2)模块
调度策略模块schedulingpolicymodule:决定那个进程获得对CPU的访问权;调度策略应当让所有进程尽可能公正得共享CPU。
体系结构相关模块architecture-specificmodule设计一组统一的具象插口来屏蔽特定体系插口芯片的硬件细节。这个模块与CPU交互以阻塞和恢复进程。这种操作包括获取每位进程须要保存的寄存器和状态信息、执行汇编代码来完成阻塞或则恢复操作。
体系结构无关模块architecture-independentmodule与调度策略模块交互将决定下一个执行的进程,之后调用体系结构相关的代码去恢复那种进程的执行。除了这么,这个模块都会调用显存管理器的插口来确保被阻塞的进程的显存映射信息被正确得保存上去。
系统调用插口模块systemcallinterface容许用户进程访问LinuxKernel明晰曝露给用户进程的资源。通过一组定义合适的基本上不变的插口(POSIX标准),将用户应用程序和Linux内核前馈,促使用户进程不会遭到内核变化的影响。
(3)数据表示
调度器维护一个数据结构——tasklist,其中的元素时每位活动的进程task_struct实例;这个数据结构不仅仅包含拿来阻塞和恢复进程的信息,也包含额外的计数和状态信息。这个数据结构在整个kernel层都可以公共访问。
(4)依赖关系、数据流、控制流
正如上面提及过的,调度器须要调用显存管理器提供的功能,去为须要恢复执行的进程选择合适的数学地址,正由于这般,所以进程调度器子系统依赖于显存管理子系统。当其他内核子系统须要等待硬件恳求完成时,它们都依赖于进程调度子系统进行进程的阻塞和恢复。这些依赖性通过函数调用和访问共享的tasklist数据结构来彰显。所有的内核子系统都要读或则写代表当前正在运行进程的数据结构,因而产生了贯串整个系统的单向数据流。
不仅内核层的数据流和控制流,OS服务层还给用户进程提供注册定时器的插口。这产生了由调度器对用户进程的控制流。一般唤起睡眠进程的用例不在正常的控制流范围,由于用户进程未能预知何时被唤起。最后,调度器与CPU交互来阻塞和恢复进程,这又产生它们之间的数据流和控制流——CPU负责打断当前正在运行的进程,并容许内核调度其他的进程运行。
2.显存管理器MemoryManager构架
(1)目标
显存管理模块负责控制进程怎么访问数学显存资源。通过硬件显存管理系统(MMU)管理进程虚拟显存和机器化学显存之间的映射。每一个进程都有自己独立的虚拟显存空间,所以两个进程可能有相同的虚拟地址,并且它们实际上在不同的数学显存区域运行。MMU提供显存保护,让两个进程的数学显存空间不相互干扰。显存管理模块还支持交换——将暂时不用的显存页换出到c盘上的交换分区,这些技术让进程的虚拟地址空间小于化学显存的大小。虚拟地址空间的大小由机器字长决定。
(2)模块
architecturespecificmodule提供访问数学显存的虚拟插口;
构架无关模块architectureindependentmodule负责每位进程的地址映射以及虚拟显存交换。当发生缺页错误时,由该模块负责决定那个显存页应当被换出显存——因为这个显存页换出选择算法几乎不须要改动,所以这儿没有完善一个独立的策略模块。
系统调用插口systemcallinterface为用户进程提供严格的访问插口(malloc和free;mmap和ummap)。这个模块容许用进程分配和释放显存、执行显存映射文件操作。
(3)数据表示
显存管理储存每位进程的虚拟显存到化学显存的映射信息。这些映射信息储存在mm_struct结构实例中,这个实例的表针又储存在每位进程的task_struct中。不仅储存映射信息,数据块中还应当储存关于显存管理器怎么获取和储存页的信息。诸如:可执行代码才能将可执行镜像作为备份储存;并且动态申请的数据则必须备份到系统页中。(这个没搞懂,请高人解惑?)
最后linux查看磁盘空间,显存管理模块还应当储存访问和技术信息,以保证系统的安全。
(4)依赖关系、数据流和控制流
显存管理器控制化学显存,当页面失败pagefault发生时,接受硬件的通知(缺页中断)——这意味着在显存管理模块和显存管理硬件之间存在单向的数据流和控制流。显存管理也依赖文件系统来支持交换和显存映射I/O——这种需求意味着显存管理器须要调用对文件系统提供的函数插口procedurecalls,往c盘中储存显存页和从c盘中取显存页。由于文件系统恳求特别慢,所以在等待显存页被换入之前,显存管理器要让进程须要步入休眠——这种需求让显存管理器调用进程调度器的插口。因为每位进程的显存映射储存在进程调度器的数据结构中,所以在显存管理器和进程调度器之间也有单向的数据流和控制流。用户进程可以构建新的进程地址空间,但是才能感知缺页错误——这里须要来自显存管理器的控制流。通常来说没有用户进程到显存管理器的数据流,并且用户进程却可以通过select系统调用,从显存管理器获取一些信息。
3.虚拟文件系统VirtualFileSystem构架
(1)目标
虚拟文件系统为储存在硬件设备上数据提供统一的访问插口。可以兼容不同的文件系统(ext2,ext4,ntf等等)。计算机中几乎所有的硬件设备都被表示为一个通用的设备驱动插口。逻辑文件系统推动与其他操作系统标准的兼容性,而且容许开发者以不同的策略实现文件系统。虚拟文件系统更进一步,容许系统管理员在任何设备上挂载任何逻辑文件系统。虚拟文件系统封装化学设备和逻辑文件系统的细节linux内核探秘:深入解析文件系统和设备驱动的架构与设计linux软件下载,而且容许用户进程使用统一的插口访问文件。
不仅传统的文件系统目标,VFS也负责装载新的可执行文件。这个任务由逻辑文件系统模块完成,致使Linux可以支持多种可执行文件。
(2)模块
devicedrivermodule
设备独立插口模块DeviceIndependentInterface:提供所有设备的同一视图
逻辑文件系统logicalfilesystem:针对每种支持的文件系统
系统独立插口systemindependentinterface提供硬件资源和逻辑文件系统都无关的插口,这个模块通过块设备节点或则字符设备节点提供所有的资源。
系统调用模块systemcallinterface提供用户进程对文件系统的统一控制访问。虚拟文件系统为用户进程屏蔽了所有特殊的特点。
(3)数据表示
所有文件使用inode表示。每位inode都记录一个文件在硬件设备上的位置信息。除了这么,inode还储存着指向逻辑文件系统模块和设备驱动的的函数表针,这种表针才能执行具体的读写操作。通过根据这些方式(就是面向对象中的虚函数的思想)储存函数表针,具体的逻辑文件系统和设备驱动可以向内核注册自己而不须要内核依赖具体的模块特点。
(4)依赖关系、数据流和控制流
一个特殊的设备驱动是ramdisk,这个设备在寻址中开辟一片区域,并把它当作持久性储存设备使用。这个设备驱动使用显存管理模块完成任务,所以在VFS与对显存管理模块存在依赖关系(图中的依赖关系反了,应当是VFS依赖于显存管理模块)、数据流和控制流。
逻辑文件系统支持网路文件系统。这个文件系统像访问本地文件一样,从另一台机器上访问文件。为了实现这个功能,一种逻辑文件系统通过网路子系统完成它的任务——这引入了VFS对网路子系统的一个依赖关系以及它们之间的控制流和数据流。
正如上面提及的,显存管理器使用VFS完成显存交换功能和显存映射I/O。另外,当VFS等待硬件恳求完成时,VFS须要使用进程调度器阻塞进程;当恳求完成时,VFS须要通过进程调度器唤起进程。最后,系统调用插口容许用户进程调用来存取数据。不像后面的子系统,VFS没有提供给用户注册不明晰调用的机制,所以没有从VFS到用户进程的控制流。
4.网路插口NetworkInterface构架
(1)目标
网路子系统让Linux系统还能通过网路与其他系统相连。这个子系统支持好多硬件设备,也支持好多网路合同。网路子系统将硬件和合同的实现细节都屏蔽掉,并具象出简单易用的插口供用户进程和其他子系统使用——用户进程和其余子系统不须要晓得硬件设备和合同的细节。
(2)模块
网路设备驱动模块networkdevicedrivers
设备独立插口模块deviceindependentinterfacemodule提供所有硬件设备的一致访问插口,致使高层子系统不须要晓得硬件的细节信息。
网路合同模块networkprotocolmodules负责实现每一个网路传输合同,比如:TCP,UDP,IP,HTTP,ARP等等~
合同无关模块protocolindependentinterface提供独立于具体合同和具体硬件设备的一致性插口。这促使其余内核子系统无需依赖特定的合同或则设备能够访问网路。
系统调用插口模块systemcallsinterface规定了用户进程可以访问的网路编程API
(3)数据表示
每位网路对象都被表示为一个套接字socket。套接字与进程关联的方式和inode节点相同。通过两个task_struct指向同一个套接字,套接字可以被多个进程共享。
(4)数据流,控制流和依赖关系
当网路子系统须要等待硬件恳求完成时,它须要通过进程调度系统将进程阻塞和唤起——这产生了网路子系统和进程调度子系统之间的控制流和数据流。除了这么,虚拟文件系统通过网路子系统实现网路文件系统(NFS)——这产生了VFS和网路子系统趾甲的数据流和控制流。
七、结论
1、Linux内核是整个Linux系统中的一层。内核从概念上由五个主要的子系统构成:进程调度器模块、内存管理模块、虚拟文件系统、网络插口模块和进程间通讯模块。这种模块之间通过函数调用和共享数据结构进行数据交互。
2、Linux内核构架推动了他的成功,这些构架致使大量的志愿开发人员可以合适得分工合作,但是促使各个特定的模块以便扩充。
可扩充性一:Linux构架通过一项数据具象技术促使这种子系统成为可扩充的——每个具体的硬件设备驱动都实现为单独的模块,该模块支持内核提供的统一的插口。通过这些方法,个人开发者只须要和其他内核开发者做最少的交互,就可以为Linux内核添加新的设备驱动。
可扩充性二:Linux内核支持多种不同的体系结构。在每位子系统中,都将体系结构相关的代码分割下来,产生单独的模块。通过这些方式,一些厂家在推出她们自己的芯片时,她们的内核开发小组只须要重新实现内核中机器相关的代码,就可以讲内核移植到新的芯片上运行。