首先一张熟悉的图来说明GNU/linux的基本体系结构:
体系的上部份是用户(或应用程序)空间,这是用户应用程序执行的地方。用户空间之下是内核空间,Linux内核正是坐落这儿。Linux内核可以进一步界定成3层:最前面是系统调用插口,用户程序通过软件中断后,调用系统内核提供的功能,这个在用户空间和内核提供的服务之间的插口称为系统调用,它实现了一些基本的功能,比如read和write;系统调用插口之下是内核代码,可以更精确地定义为独立于体系结构的内核代码linux内核24版源代码分析大全(清晰版),这种代码是Linux所支持的所有处理器体系结构所通用的;内核代码之下是依赖于体系结构的代码,构成了一般称为BSP(BoardSupportPackage)的部份,这种代码用作给定体系结构的处理器和特定于平台的代码。
小编自己整理了一些个人认为比较好的学习书籍、视频资料有须要的可以私信回复【内核】自行免费发放哦!!
之后介绍Linux内核的五个子系统:
Linux内核主要由进程调度(SCHED)、内存管理(MM)、虚拟文件系统(VFS)、网络插口(NET)和进程间通讯(IPC)5个子系统组成,如图1所示。
1.进程调度
进程调度控制系统中的多个进程对CPU的访问,致使多个进程能在CPU中“微观串行,宏观并行”地执行。进程调度处于系统的中心位置,内核中其他的子系统都依赖它,由于每位子系统都须要挂起或恢复进程。
如上图2所示,Linux的进程在几个状态间进行切换。在设备驱动编程中,当恳求的资源不能得到满足时,驱动通常会调度其他进程执行,并使本进程步入睡眠状态,直至它恳求的资源被释放,就会被唤起而步入就绪态。睡眠分成可被打断的睡眠和不可被打断的睡眠,二者的区别在于可被打断的睡眠在收到讯号的时侯会醒。
在设备驱动编程中,当恳求的资源不能得到满足时,驱动通常会调度其他进程执行,其对应进程步入睡眠状态,直至它恳求的资源被释放,就会被唤起而步入就绪态。设备驱动中LINUX社区,假如须要几个并发执行的任务,可以启动内核线程,启动内核线程的函数为:
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
当用户使用系统提供的库函数进行进程编程,用户可以动态地创建进程,进程之间还有等待,互斥等操作,这种操作都是由linux内核来实现的。linux内核通过进程管理子系统实现了进程有关的操作,在linux系统上,所有的估算工作都是通过进程表现的,进程可以是短期的(执行一个命令),也可以是常年的(一种网路服务)。linux系统是一种动态系统,通过进程管理才能适应不断变化的估算需求。
在用户空间,进程是由进程标识符(PID)表示的。从用户角度看,一个PID是一个数字值,可以惟一标示一个进程,一个PID值在进程的整个生命周期中不会修改,而且PID可以在进程销毁后被重新使用。创建进程可以使用几种方法,可以创建一个新的进程,也可以创建当前进程的子进程。
在linux内核空间,每位进程都有一个独立的数据结构,拿来保存该进程的ID、优先级、地址的空间等信息,这个结构也被称做进程控制块(ProcessControlBlock)。所谓的进程管理就是对进程控制块的管理。
linux的进程是通过fork()函数系统调用形成的。调用fork()的进程称作父进程,生成的进程称作子进程。子进程被创建的时侯,不仅进程ID外,其它数据结构与父进程完全一致。在fork()系统调用创建显存以后,子进程马上被加入内核的进程调试队列,之后使用exec()系统调用,把程序的代码加入到子进程的地址空间,然后子进程就开始执行自己的代码。
在一个系统上可以有多个进程,然而通常情况下只有一个CPU,在同一个时刻只能有一个进程在工作,虽然有多个CPU,也不可能和进程的数目一样多。若果让若干的进程都能在CPU上工作,这就是进程管理子系统的工作。linux内核设计了储存进程队列的结构,在一个系统上会有若干队列,分别储存不同状态的进程。一个进程可以有若干状态,具体是由操作系统来定义的,而且起码包含运行态、就绪态和等待3种状态,内核设计了对应的队列储存对应状态的进程控制块。
当一个用户进程被加载后,会步入就绪态,被加入到就绪态队列,CPU时间被轮转入就绪态队列后,切换到进程的代码,进程被执行,当进程的时间片到了之后被换出。假如进程发生I/O操作也会被提早被换出,而且储存到等待队列,当I/O恳求返回后,进程又被装入就绪队列。linux系统对进程队列的管理设计了若干不同的方式,主要的目的是提升进程调试的稳定性。
2.显存管理
显存管理的主要作用是控制多个进程安全地共享主显存区域。当CPU提供显存管理单元(MMU)时,Linux显存管理完成为每位进程进行虚拟显存到化学显存的转换。Linux2.6引入了对无MMUCPU的支持。
如右图3所示,通常而言,Linux的每位进程享有4GB的显存空间,0~3GB属于用户空间,3~4GB属于内核空间,内核空间对常规显存、I/O设备显存以及高档显存存在不同的处理方法。
使用虚拟显存技术的计算机,显存管理的硬件根据分页形式管理显存。分页方法是把计算机系统的数学显存根据相同大小等分,每位显存分片叫做显存页,一般显存页大小是4KB。Linux内核的显存管理子系统管理虚拟显存与数学显存之间的映射关系,以及系统可用显存空间。显存管理要管理的除了是4KB缓冲区。Linux提供了对4KB缓冲区的具象,比如slab分配器。这些显存管理模式使用4KB缓冲区为基数,之后从中分配结构,并跟踪显存页使用情况,例如什么显存页是满的,什么页面没有完全使用,什么页面为空。这样就容许该模式依据系统须要来动态调整显存使用。
在支持多用户的系统上,因为显存占用的减小,容易出现化学显存被消耗尽的情况。为了解决数学显存被用尽的问题,显存管理子系统规定页面可以移出显存并装入c盘中,这个过程称为交换。显存管理的源代码可以在./linux/mm中找到。
3.虚拟文件系统
如右图4所示,Linux虚拟文件系统(VFS)隐藏各类了硬件的具体细节,为所有的设备提供了统一的插口。并且,它独立于各个具体的文件系统,是对各类文件系统的一个具象,它使用超级块superblock储存文件系统相关信息,使用索引节点inode储存文件的化学信息,使用目录项dentry储存文件的逻辑信息。
在不同格式的文件分区上,程序都可以正确地读写文件,但是结果是一样的。有时在使用linux系统的时侯发觉,可以在不同类型的文件分区内直接复制文件,对应用程序来说,并不晓得文件系统的类型,甚至不晓得文件的类型,这就是虚拟文件系统在背后做的工作。虚拟文件系统屏蔽了不同文件系统间的差别,向用户提供了统一的插口。
虚拟文件系统,即VFS(VirtualFileSystem)是Linux内核中的一个软件具象层。它通过一些数据结构及其方式向实际的文件系统如ext2,vfat等提供插口机制。通过使用同一套文件I/O系统调用即可对Linux中的任意文件进行操作而无需考虑其所在的具体文件系统格式;更进一步,文件操作可以在不同文件系统之间进行。在linux系统中,一切都可以被看做是文件。除了普通的文本文件、目录可以当作文件进行处理,但是字符设备、块设备、套接字等都可以被当作文件进行处理。这种文件尽管类型不同,而且却使用同一种操作方式。这也是UNIX/Linux设计的基本哲学之一。
虚拟文件系统(简称VFS)是实现“一切都是文件”特性的关键,是Linux内核的一个软件层,向用户空间的程序提供文件系统插口;同时提供了内核中的一个具象功能,容许不同类型的文件系统存在。VFS可以被理解为一种具象的插口标准,系统中所有的文件系统除了借助VFS共存,也借助VFS协同工作。为了才能支持不同的文件系统,VFS定义了所有文件系统都支持的、最基本的一个概念上的插口和数据结构,在实现一个具体的文件系统的时侯,须要向VFS提供符合VFS标准的插口和数据结构,不同的文件系统可能在实体概念上有差异,而且使用VFS插口时须要和VFS定义的概念保持一致,只有这样,就能实现对用户的文件系统无关性。VFS隐藏了具体文件系统的操作细节,所以,在VFS这一层以及内核其他部份看来,所有的文件系统都是相同的。对文件系统访问的系统调用通过VFS软件层处理,VFS按照访问的恳求调用不同的文件系统驱动的函数处理用户的恳求。文件系统的代码在访问数学设备的时侯,须要使用化学设备驱动访问真正的硬件。
4.网路插口
网路插口提供了对各类网路标准的存取和各类网路硬件的支持。如右图5所示,在Linux中网路插口可分为网路合同和网路驱动程序,网路合同部份负责实现每一种可能的网路传输合同,网路设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。
写网路应用程序,使用socket通过TCP/IP合同与其他机器通讯,和上面介绍的内核子系统相像,socket相关的函数也是通过内核的子系统完成的,担当这部份任务的是内核的网路子系统,有时也把这部份代码称为“网络堆栈”。Linux内核提供了优秀的网路处理能力和功能,这与网路堆栈代码的设计思想是分不开的,Linux的网路堆栈部份沿用了传统的层次结构,网路数据从用户进程抵达实际的网路设备须要四个层次:用户进程,套接字,网路合同,网路设备。
实际上,在每层上面还可以分为很多层次,数据传输的路径是根据层次来的,不能跨越某个层次。linux网路子系统对网路层次采用了类似面向对象的设计思路,把须要处理的层次具象为不同的实体,而且定义了实体之间的关系和数据处理流程:
(1)网路合同:网路合同可以理解为一种语言,用于网路中不同设备之间的通讯,是一种通讯的规范。
(2)套接字:套接字是内核与用户程序的插口,一个套接字对应一个数据联接,但是向用户提供了文件I/O,用户可以像操作文件一样在数据联接上收发数据,具体的合同处理由网路合同部份处理。套接字是用户使用网路的插口。
(3)设备插口:设备插口是网路子系统中软件和硬件的插口,用户的数据最终是须要通过网路硬件设备发送和接收的,网路设备千差万别,设备驱动也不尽相同,通过设备插口屏蔽了具体设备驱动的差别。
(4)网路缓冲区:网路缓冲区俗称为套接字缓冲区(sk_buff),是网路子系统中的一个重要结构。网路传输数据存在许多不定诱因,不仅化学设备对传输数据的限制(比如MMU),网路遭到干扰、丢包、重传等,还会导致数据的不稳定,网路缓冲区通过对网路数据的重新整理,使业务处理的数据包是完整的。网路缓冲区是显存中的一块缓冲区,是网路系统与显存管理的插口。
5.进程通讯
进程通讯支持提供进程之间的通讯,Linux支持进程间的多种通讯机制,包含讯号量、共享显存、管道等,这种机制可协助多个进程、多资源的互斥访问、进程间的同步和消息传递。
子系统之间的依赖关系:
Linux内核的5个组成部份之间的依赖关系如下:
·进程调度与显存管理之间的关系:这两个子系统相互依赖。在多道程序环境下,程序要运行必须为之创建进程linux内核24版源代码分析大全(清晰版)linux培训机构,而创建进程的第一件事情,就是将程序和数据放入显存。
·进程间通讯与显存管理的关系:进程间通讯子系统要依赖显存管理支持共享显存通讯机制,这些机制准许两个进程不仅拥有自己的私有空间,还可以存取共同的显存区域。
·虚拟文件系统与网路插口之间的关系:虚拟文件系统借助网路插口支持网路文件系统(NFS),也借助显存管理支持RAMDISK设备。
·内存管理与虚拟文件系统之间的关系:显存管理借助虚拟文件系统支持交换,交换进程(swapd)定期由调度程序调度,这也是显存管理依赖于进程调度的唯一缘由。当一个进程存取的显存映射被换出时,显存管理向文件系统发出恳求,同时,挂起当前正在运行的进程。
不仅这种依赖关系外,内核中的所有子系统还要依赖于一些共同的资源。这种资源包括所有子系统都用到的类库,如分配和释放显存空间的函数、打印警告或错误信息的函数及系统提供的调试解释器等。
原文链接;https://blog.csdn.net/xiaomage_307_/article/details/79117881?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163782776716780357286570%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163782776716780357286570&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-79117881.first_rank_v2_pc_rank_v29&utm_term=linux%E5%86%85%E6%A0%B8%E8%AE%BE%E5%A4%87%E5%AD%90%E7%B3%BB%E7%BB%9F&spm=1018.2226.3001.4187