深入理解Linux Kernel内核整体架构(图文详解)

一,前言

本文是“Linux内核分析”系列文章的第一篇,会以内核的核心功能为出发点,描述Linux内核的整体架构,以及架构之下主要的软件子系统。之后,会介绍Linux内核源文件的目录结构,并和各个软件子系统对应。


注:本文和其它的“Linux内核分析”文章都基于如下约定:

  • a) 内核版本为Linux 3.10.29(该版本是一个long term的版本,会被Linux社区持续维护至少2年)。
  • b) 鉴于嵌入式系统大多使用ARM处理器,因此涉及到体系结构部分的内容,都以ARM为分析对象

二,Linux内核的核心功能

如下图所示,Linux内核只是Linux操作系统一部分。对下,它管理系统的所有硬件设备;对上,它通过系统调用,向Library Routine(例如C库)或者其它应用程序提供接口。


因此,其核心功能就是:管理硬件设备,供应用程序使用。而现代计算机(无论是PC还是嵌入式系统)的标准组成,就是CPU、Memory(内存和外存)、输入输出设备、网络设备和其它的外围设备。所以为了管理这些设备,Linux内核提出了如下的架构。

资料直通车:最新Linux内核源码资料文档+视频资料icon-default.png?t=M85Bhttps://docs.qq.com/doc/DTmFTc29xUGdNSnZ2

内核学习地址:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈icon-default.png?t=M85Bhttps://ke.qq.com/course/4032547?flowToken=1040236

三,Linux内核的整体架构

3.1 整体架构和子系统划分


上图说明了Linux内核的整体架构。根据内核的核心功能,Linux内核提出了5个子系统,分别负责如下的功能:
1. Process Scheduler,也称作进程管理、进程调度。负责管理CPU资源,以便让各个进程可以以尽量公平的方式访问CPU。
2. Memory Manager,内存管理。负责管理Memory(内存)资源,以便让各个进程可以安全地共享机器的内存资源。另外,内存管理会提供虚拟内存的机制,该机制可以让进程使用多于系统可用Memory的内存,不用的内存会通过文件系统保存在外部非易失存储器中,需要使用的时候,再取回到内存中。
3. VFS(Virtual File System),虚拟文件系统。Linux内核将不同功能的外部设备,例如Disk设备(硬盘、磁盘、NAND Flash、Nor Flash等)、输入输出设备、显示设备等等,抽象为可以通过统一的文件操作接口(open、close、read、write等)来访问。这就是Linux系统“一切皆是文件”的体现(其实Linux做的并不彻底,因为CPU、内存、网络等还不是文件,如果真的需要一切皆是文件,还得看贝尔实验室正在开发的"Plan 9”的)。
4. Network,网络子系统。负责管理系统的网络设备,并实现多种多样的网络标准。
5. IPC(Inter-Process Communication),进程间通信。IPC不管理任何的硬件,它主要负责Linux系统中进程之间的通信。

3.2 进程调度(Process Scheduler)

进程调度是Linux内核中最重要的子系统,它主要提供对CPU的访问控制。因为在计算机中,CPU资源是有限的,而众多的应用程序都要使用CPU资源,所以需要“进程调度子系统”对CPU进行调度管理。
进程调度子系统包括4个子模块(见下图),它们的功能如下:


1. Scheduling Policy,实现进程调度的策略,它决定哪个(或哪几个)进程将拥有CPU。
2. Architecture-specific Schedulers,体系结构相关的部分,用于将对不同CPU的控制,抽象为统一的接口。这些控制主要在suspend和resume进程时使用,牵涉到CPU的寄存器访问、汇编指令操作等。
3. Architecture-independent Scheduler,体系结构无关的部分。它会和“Scheduling Policy模块”沟通,决定接下来要执行哪个进程,然后通过“Architecture-specific Schedulers模块”resume指定的进程。
4. System Call Interface,系统调用接口。进程调度子系统通过系统调用接口,将需要提供给用户空间的接口开放出去,同时屏蔽掉不需要用户空间程序关心的细节。
3.3 内存管理(Memory Manager, MM)
内存管理同样是Linux内核中最重要的子系统,它主要提供对内存资源的访问控制。Linux系统会在硬件物理内存和进程所使用的内存(称作虚拟内存)之间建立一种映射关系,这种映射是以进程为单位,因而不同的进程可以使用相同的虚拟内存,而这些相同的虚拟内存,可以映射到不同的物理内存上。

内存管理子系统包括3个子模块(见下图),它们的功能如下:


1. Architecture Specific Managers,体系结构相关部分。提供用于访问硬件Memory的虚拟接口。
2. Architecture Independent Manager,体系结构无关部分。提供所有的内存管理机制,包括:以进程为单位的memory mapping;虚拟内存的Swapping。
3. System Call Interface,系统调用接口。通过该接口,向用户空间程序应用程序提供内存的分配、释放,文件的map等功能。

3.4 虚拟文件系统(Virtual Filesystem, VFS)

传统意义上的文件系统,是一种存储和组织计算机数据的方法。它用易懂、人性化的方法(文件和目录结构),抽象计算机磁盘、硬盘等设备上冰冷的数据块,从而使对它们的查找和访问变得容易。因而文件系统的实质,就是“存储和组织数据的方法”,文件系统的表现形式,就是“从某个设备中读取数据和向某个设备写入数据”。
随着计算机技术的进步,存储和组织数据的方法也是在不断进步的,从而导致有多种类型的文件系统,例如FAT、FAT32、NTFS、EXT2、EXT3等等。而为了兼容,操作系统或者内核,要以相同的表现形式,同时支持多种类型的文件系统,这就延伸出了虚拟文件系统(VFS)的概念。VFS的功能就是管理各种各样的文件系统,屏蔽它们的差异,以统一的方式,为用户程序提供访问文件的接口。
我们可以从磁盘、硬盘、NAND Flash等设备中读取或写入数据,因而最初的文件系统都是构建在这些设备之上的。这个概念也可以推广到其它的硬件设备,例如内存、显示器(LCD)、键盘、串口等等。我们对硬件设备的访问控制,也可以归纳为读取或者写入数据,因而可以用统一的文件操作接口访问。Linux内核就是这样做的,除了传统的磁盘文件系统之外,它还抽象出了设备文件系统、内存文件系统等等。这些逻辑,都是由VFS子系统实现。
VFS子系统包括6个子模块(见下图),它们的功能如下:


1. Device Drivers,设备驱动,用于控制所有的外部设备及控制器。由于存在大量不能相互兼容的硬件设备(特别是嵌入式产品),所以也有非常多的设备驱动。因此,Linux内核中将近一半的Source Code都是设备驱动,大多数的Linux底层工程师(特别是国内的企业)都是在编写或者维护设备驱动,而无暇估计其它内容(它们恰恰是Linux内核的精髓所在)。
2. Device Independent Interface, 该模块定义了描述硬件设备的统一方式(统一设备模型),所有的设备驱动都遵守这个定义,可以降低开发的难度。同时可以用一致的形式向上提供接口。
3. Logical Systems,每一种文件系统,都会对应一个Logical System(逻辑文件系统),它会实现具体的文件系统逻辑。
4. System Independent Interface,该模块负责以统一的接口(快设备和字符设备)表示硬件设备和逻辑文件系统,这样上层软件就不再关心具体的硬件形态了。
5. System Call Interface,系统调用接口,向用户空间提供访问文件系统和硬件设备的统一的接口。
3.5 网络子系统(Net)
网络子系统在Linux内核中主要负责管理各种网络设备,并实现各种网络协议栈,最终实现通过网络连接其它系统的功能。在Linux内核中,网络子系统几乎是自成体系,它包括5个子模块(见下图),它们的功能如下:


1. Network Device Drivers,网络设备的驱动,和VFS子系统中的设备驱动是一样的。
2. Device Independent Interface,和VFS子系统中的是一样的。
3. Network Protocols,实现各种网络传输协议,例如IP, TCP, UDP等等。
4. Protocol Independent Interface,屏蔽不同的硬件设备和网络协议,以相同的格式提供接口(socket)。
5. System Call interface,系统调用接口,向用户空间提供访问网络设备的统一的接口。
至于IPC子系统,由于功能比较单纯,这里就不再描述了。

四,Linux内核源代码的目录结构

Linux内核源代码包括三个主要部分:
1. 内核核心代码,包括第3章所描述的各个子系统和子模块,以及其它的支撑子系统,例如电源管理、Linux初始化等
2. 其它非核心代码,例如库文件(因为Linux内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等
3. 编译脚本、配置文件、帮助文档、版权说明等辅助性文件
下图是使用ls命令看到的内核源代码的顶层目录结构,具体描述如下:

  1. include/ ---- 内核头文件,需要提供给外部模块(例如用户空间代码)使用。
  2. kernel/ ---- Linux内核的核心代码,包含了3.2小节所描述的进程调度子系统,以及和进程调度相关的模块。
  3. mm/ ---- 内存管理子系统(3.3小节)。
  4. fs/ ---- VFS子系统(3.4小节)。
  5. net/ ---- 不包括网络设备驱动的网络子系统(3.5小节)。
  6. ipc/ ---- IPC(进程间通信)子系统。
  7. arch// ---- 体系结构相关的代码,例如arm, x86等等。
  8. arch//mach- ---- 具体的machine/board相关的代码。
  9. arch//include/asm ---- 体系结构相关的头文件。
  10. arch//boot/dts ---- 设备树(Device Tree)文件。
  11. init/ ---- Linux系统启动初始化相关的代码。
  12. block/ ---- 提供块设备的层次。
  13. sound/ ---- 音频相关的驱动及子系统,可以看作“音频子系统”。
  14. drivers/ ---- 设备驱动(在Linux kernel 3.10中,设备驱动占了49.4的代码量)。
  15. lib/ ---- 实现需要在内核中使用的库函数,例如CRC、FIFO、list、MD5等。
  16. crypto/ ----- 加密、解密相关的库函数。
  17. security/ ---- 提供安全特性(SELinux)。
  18. virt/ ---- 提供虚拟机技术(KVM等)的支持。
  19. usr/ ---- 用于生成initramfs的代码。
  20. firmware/ ---- 保存用于驱动第三方设备的固件。
  21. samples/ ---- 一些示例代码。
  22. tools/ ---- 一些常用工具,如性能剖析、自测试等。
  23. Kconfig, Kbuild, Makefile, scripts/ ---- 用于内核编译的配置文件、脚本等。
  24. COPYING ---- 版权声明。
  25. MAINTAINERS ----维护者名单。
  26. CREDITS ---- Linux主要的贡献者名单。
  27. REPORTING-BUGS ---- Bug上报的指南。
  28. Documentation, README ---- 帮助、说明文档。
  • 1
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Preface The Audience for This Book Organization of the Material Level of Description Overview of the Book Background Information Conventions in This Book How to Contact Us Safari? Enabled Acknowledgments Chapter 1. Introduction Section 1.1. Linux Versus Other Unix-Like Kernels Section 1.2. Hardware Dependency Section 1.3. Linux Versions Section 1.4. Basic Operating System Concepts Section 1.5. An Overview of the Unix Filesystem Section 1.6. An Overview of Unix Kernels Chapter 2. Memory Addressing Section 2.1. Memory Addresses Section 2.2. Segmentation in Hardware Section 2.3. Segmentation in Linux Section 2.4. Paging in Hardware Section 2.5. Paging in Linux Chapter 3. Processes Section 3.1. Processes, Lightweight Processes, and Threads Section 3.2. Process Descriptor Section 3.3. Process Switch Section 3.4. Creating Processes Section 3.5. Destroying Processes Chapter 4. Interrupts and Exceptions Section 4.1. The Role of Interrupt Signals Section 4.2. Interrupts and Exceptions Section 4.3. Nested Execution of Exception and Interrupt Handlers Section 4.4. Initializing the Interrupt Descriptor Table Section 4.5. Exception Handling Section 4.6. Interrupt Handling Section 4.7. Softirqs and Tasklets Section 4.8. Work Queues Section 4.9. Returning from Interrupts and Exceptions Chapter 5. Kernel Synchronization Section 5.1. How the Kernel Services Requests Section 5.2. Synchronization Primitives Section 5.3. Synchronizing Accesses to Kernel Data Structures Section 5.4. Examples of Race Condition Prevention Chapter 6. Timing Measurements Section 6.1. Clock and Timer Circuits Section 6.2. The Linux Timekeeping Architecture Section 6.3. Updating the Time and Date Section 6.4. Updating System Statistics Section 6.5. Software Timers and Delay Functions Section 6.6. System Calls Related to Timing Measurements Chapter 7. Process Scheduling Section 7.1. Scheduling Policy Section 7.2. The Scheduling Algorithm Section 7.3. Data Structures Used by the Scheduler Section 7.4. Functions Used by the Scheduler Section 7.5. Runqueue Balancing in Multiprocessor Systems Section 7.6. System Calls Related to Scheduling Chapter 8. Memory Management Section 8.1. Page Frame Management Section 8.2. Memory Area Management Section 8.3. Noncontiguous Memory Area Management Chapter 9. Process Address Space Section 9.1. The Processs Address Space Section 9.2. The Memory Descriptor Section 9.3. Memory Regions Section 9.4. Page Fault Exception Handler Section 9.5. Creating and Deleting a Process Address Space Section 9.6. Managing the Heap Chapter 10. System Calls Section 10.1. POSIX APIs and System Calls Section 10.2. System Call Handler and Service Routines Section 10.3. Entering and Exiting a System Call Section 10.4. Parameter Passing Section 10.5. Kernel Wrapper Routines Chapter 11. Signals Section 11.1. The Role of Signals Section 11.2. Generating a Signal Section 11.3. Delivering a Signal Section 11.4. System Calls Related to Signal Handling Chapter 12. The Virtual Filesystem Section 12.1. The Role of the Virtual Filesystem (VFS) Section 12.2. VFS Data Structures Section 12.3. Filesystem Types Section 12.4. Filesystem Handling Section 12.5. Pathname Lookup Section 12.6. Implementations of VFS System Calls Section 12.7. File Locking Chapter 13. I/O Architecture and Device Drivers Section 13.1. I/O Architecture Section 13.2. The Device Driver Model Section 13.3. Device Files Section 13.4. Device Drivers Section 13.5. Character Device Drivers Chapter 14. Block Device Drivers Section 14.1. Block Devices Handling Section 14.2. The Generic Block Layer Section 14.3. The I/O Scheduler Section 14.4. Block Device Drivers Section 14.5. Opening a Block Device File Chapter 15. The Page Cache Section 15.1. The Page Cache Section 15.2. Storing Blocks in the Page Cache Section 15.3. Writing Dirty Pages to Disk Section 15.4. The sync( ), fsync( ), and fdatasync( ) System Calls Chapter 16. Accessing Files Section 16.1. Reading and Writing a File Section 16.2. Memory Mapping Section 16.3. Direct I/O Transfers Section 16.4. Asynchronous I/O Chapter 17. Page Frame Reclaiming Section 17.1. The Page Frame Reclaiming Algorithm Section 17.2. Reverse Mapping Section 17.3. Implementing the PFRA Section 17.4. Swapping Chapter 18. The Ext2 and Ext3 Filesystems Section 18.1. General Characteristics of Ext2 Section 18.2. Ext2 Disk Data Structures Section 18.3. Ext2 Memory Data Structures Section 18.4. Creating the Ext2 Filesystem Section 18.5. Ext2 Methods Section 18.6. Managing Ext2 Disk Space Section 18.7. The Ext3 Filesystem Chapter 19. Process Communication Section 19.1. Pipes Section 19.2. FIFOs Section 19.3. System V IPC Section 19.4. POSIX Message Queues Chapter 20. Program ExZecution Section 20.1. Executable Files Section 20.2. Executable Formats Section 20.3. Execution Domains Section 20.4. The exec Functions Appendix A. System Startup Section A.1. Prehistoric Age: the BIOS Section A.2. Ancient Age: the Boot Loader Section A.3. Middle Ages: the setup( ) Function Section A.4. Renaissance: the startup_32( ) Functions Section A.5. Modern Age: the start_kernel( ) Function Appendix B. Modules Section B.1. To Be (a Module) or Not to Be? Section B.2. Module Implementation Section B.3. Linking and Unlinking Modules Section B.4. Linking Modules on Demand Bibliography Books on Unix Kernels Books on the Linux Kernel Books on PC Architecture and Technical Manuals on Intel Microprocessors Other Online Documentation Sources Research Papers Related to Linux Development About the Authors Colophon Index
Linux默认内核是由Linus Torvalds开发的Linux内核。要进行内核配置,可以使用make menuconfig或make config命令进行交互式配置,也可以使用make defconfig命令使用默认配置。以下是更详细的步骤: 1. 下载Linux内核源代码,并解压缩。 2. 进入内核源代码目录,运行make menuconfig命令,进入交互式配置界面。 3. 在界面中,可以选择不同的内核配置选项。例如,选择“General setup”选项,可以配置内核的基本设置,如内核版本号、支持的处理器架构、系统时间等。 4. 选择“Processor type and features”选项,可以配置内核的处理器类型和特性,如是否支持超线程、是否支持SSE指令集等。 5. 选择“Networking support”选项,可以配置内核网络的支持,如是否启用IPv6、是否支持网络设备驱动等。 6. 选择“File systems”选项,可以配置内核对文件系统的支持,如是否支持ext4、NTFS等。 7. 配置完成后,可以保存配置并退出。此时,内核配置文件会被保存为.config文件。 8. 运行make命令,编译内核。编译完成后,会生成一个内核镜像文件。 9. 将内核镜像文件拷贝到/boot目录下。 10. 配置引导程序,使其启动新的内核。具体步骤因引导程序而异,这里不再赘述。 以上是Linux内核配置的基本步骤。需要注意的是,配置内核时需要根据实际需求进行选择,不要选择过多或不必要的功能,以免浪费系统资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简说Linux内核

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值