1、内核行数Linux内核分为CPU调度、内存管理、网络和存储四个子系统,硬件的驱动程序有数百个。代码量大得惊人。先说最早的内核linux0.11。可以说很多驱动工程师都研究过下面这本书。我花了大约一个半月的时间才读完。我们来看看内核代码量的统计情况。2020年1月1日,Linux内核Git源代码树中的代码达到2780万行。phoronix网站统计了进入2020年Linux内核的一些源码数据,做了一个总结。从统计数据来看,Linux内核源代码树共有:27,852,148行(包括文档、Kconfig文件、树中的用户空间实用程序等),887,925次提交,21,074位不同作者,2780万行代码分布在66,492个文件。Linux内核从最初的1万行代码到现在的2780万行代码,是全球精英共同贡献的成果。按照一天10000行的速度,需要2700天,7年多。这还是建立在什么都懂一次,所有的代码逻辑都看完就明白了,还没有忘记的基础上。其实就算我们真的读完了,过几年内核也会有非常大的变化,可以说我们一辈子也读不懂Linux内核的代码。Linux内核Git源代码树中的代码已经达到2780万行,只有2%的核心代码是LinusTorvalds自己编写的,其余都是其他个人和组织贡献的。LinusTorvalds公开了Linux,但对需要合并的新代码和新方法的选择保留最终决定权。除了LinusTorvalds之外,对内核贡献最多的还有DavidS.Miller、MarkBrown、TakashiIwai、ArndBergmann、AlViro和MauroCarvalhoChehab。至于参与企业,从域名统计来看,谷歌、英特尔和红帽位居前列。2、内核目录文件的大小然而,目前的内核已经臃肿到年久失修的地步。以最新的linux-4.1.15为例:整个内核源代码约793M:驱动代码约占一半,约380M:系统相关代码约134M:网络子系统相关代码约26M:与文件系统相关的代码37M:linux内核的核心代码约6.8M:要完全理解这些目录中的任何一个都非常困难。3、内核子系统什么是内核:在计算机科学中,是一种计算机程序,用于管理软件发出的数据I/O(输入输出)需求,并将这些需求翻译成数据处理指令交给中央处理器(CPU)和计算机中的其他电子元件进行处理,是现代操作系统最基本的部分。它是软件的一部分,为许多应用程序提供对计算机硬件的安全访问。这种访问是有限的,由内核决定程序何时以及多长时间在硬件的特定部分上运行。linux内核代码涉及的知识点包括汇编指令、c语言、硬件组成原理、操作系统、数据结构与算法、各种外围总线、驱动程序、网络协议栈等。直接在硬件上操作非常复杂。所以内核通常会提供硬件抽象方法来完成这些操作。通过进程间通信机制和系统调用,应用进程可以间接控制所需的硬件资源(尤其是处理器和IO设备)。顶部是用户(或应用程序)空间。这是用户应用程序执行的地方。用户空间下面是内核空间,Linux内核所在的地方。GNUC库(glibc)也在这里。它为内核提供了一个系统调用接口,也提供了一种在用户空间应用程序和内核之间切换的机制。内核和用户空间应用程序使用不同的受保护地址空间。每个用户空间进程使用自己的虚拟地址空间,而内核占用单独的地址空间。Linux内核可以进一步分为3层。最上面是系统调用接口,实现了读写等一些基本功能。系统调用接口下面是内核代码,可以更准确的定义为架构无关的内核代码。这些代码对于Linux支持的所有处理器架构都是通用的。在这些代码之下是与体系结构相关的代码,这些代码构成了通常所说的BSP(板级支持包)。这些代码用作给定体系结构的特定于处理器和平台的代码。内核的主要系统包括:SCI:系统调用接口PM:进程管理VFS:虚拟文件系统MM:内存管理NetworkStack:内核协议栈Arch:架构DD:设备驱动1系统调用接口SCI层提供了一定的机制来执行从用户空间到内核的slaves函数调用。此接口依赖于体系结构,即使在同一处理器系列中也是如此。SCI其实是一个非常有用的函数调用复用和解复用服务。在./linux/kernel中,您将找到SCI实现,并在./linux/arch中找到体系结构相关的部分。2.流程管理流程管理的重点是流程的执行。在内核中,这些进程称为线程,代表单个处理器虚拟化(线程代码、数据、堆栈和CPU寄存器)。在用户空间中,术语进程是常用的,但Linux实现并不区分这两个概念(进程和线程)。内核通过SCI提供应用程序编程接口(API)来创建新进程(fork、exec或PortableOperatingSystemInterface[POSIX]函数)、停止进程(kill、exit)以及它们之间的通信和同步(信号或POSIX机制)。3内存管理内核管理的另一个重要资源是内存。为了提高效率,如果虚拟内存由硬件管理,则内存在所谓的内存页面(大多数架构为4KB)中进行管理。Linux涵盖了可用内存的管理方式,以及用于物理和虚拟映射的硬件机制。4虚拟文件系统虚拟文件系统(VFS)是Linux内核的一个非常有用的方面,因为它为文件系统提供了通用接口抽象。VFS在SCI和内核支持的文件系统之间提供了一个交换层。在VFS之上是一个通用API抽象,用于打开、关闭、读取和写入等功能。VFS下面是文件系统抽象,定义了上层功能的实现。它们是给定文件系统(50+)的插件。文件系统的源代码可以在./linux/fs中找到。文件系统层下面是buffercache,它为文件系统层提供了一个通用的功能集(与具体的文件系统无关)。该缓存层通过将数据保留一段时间(或预取数据以使其在需要时可用)来优化对物理设备的访问。缓冲区缓存下面是设备驱动程序,它实现了到特定物理设备的接口。5网络栈网络栈的设计遵循模拟协议本身的分层架构。回想一下,互联网协议(IP)是传输协议(通常称为传输控制协议或TCP)之下的核心网络层协议。TCP之上是socket层,通过SCI调用。套接字层是网络子系统的标准API,为各种网络协议提供用户接口。从原始帧访问到IP协议数据单元(PDU),再到TCP和用户数据报协议(UDP),套接字层提供了一种标准化的方式来管理连接和在端点之间移动数据。内核中的网络源代码可以在./linux/net中找到。6设备驱动程序Linux内核中有大量的设备驱动程序代码,可以运行特定的硬件设备。Linux源码树提供了一个drivers子目录,里面又分为各种支持设备,比如Bluetooth、I2C、serial等,设备驱动的代码可以在./linux/drivers中找到。下图形象的解释了Linux内核里有什么!4.如何学习内核?1、学习Linux内核源码主线大而全。一个人再聪明、再有活力,也不可能把它看完。了解所有linux内核源代码。一口君建议按照以下主线深入研究:linux驱动架构linux网络子系统linux内核启动过程linux内存管理机制linux调度器linux进程管理linux虚拟机制(kvm)linux内核实时技术沿着某条主线,深入其中,在研究清楚这条主线的同时,拓展、渗透、借鉴其他主线。之所以在这里把驱动列为学习内核的切入点,是因为内核实现了很多外设驱动的架构,比如I2C、SPI、UART、PCIE、字符设备、网络设备、块设备等。我们可以从最基本的字符开始学习设备,学习如何编写一个简单的模块,学习如何编写一些简单的设备如LED,KEY,ADC等的驱动。可以说驱动是最简单的入门点为我们学习内核,由点到线,由线到面,由面到体,深入不断地完善,是学习linux内核源码的有效途径。2.读码工具从两个角度介绍读码方法。一方面是选择更有效的代码阅读工具。一口君强烈推荐:sourceinsight,阅读代码的神器!你也可以使用vscode或vim+ctags的组合。但是,一口君拥有十多年的行业经验,99%以上的开发者选择SI阅读内核代码。代码不是写给人类阅读的,而是写给机器运行的。所以我们在理解别人的代码的时候,不能像看小说一样去读代码,而应该像化石一样去研究、解密。有时候我们往往需要自己去实现对方的一段代码,然后举一反三,看看我们会怎么实现,这样才能真正理解。3.内核版本学习有人建议先阅读一些低版本的内核,比如0.01版本,总代码量只有10000行左右。看了这段代码大概一个月应该就比较清楚了。但是修改后的代码和现在的代码有很大的不同,基本的思路看完也能理解,但是对理解现有代码的帮助不是特别明显。3.10版本以后的内核都支持设备树!因此,一口君建议大家尽量选择3.10版本之后的代码进行阅读和学习。最好选择开发板来学习!选择开发板一定要选择信息更齐全、售后服务更好的品牌!不然学习中遇到一个小问题,可能会卡上一两周。无形中增加了学习成本,要知道时间就是金钱!对于初学者,强烈推荐正点原子的开发板!4、学习Linux最重要的是培养自己写代码的能力,了解Linux的框架结构Linux内核中的大部分代码都是由地球上最顶尖的技术专家编写的。这些代码高内聚低耦合,准确率、简洁性和质量都相当高。每次看到一段高质量的代码,一口君都会被枯燥代码背后隐藏的设计思想所震撼和折服!阅读内核代码简直就是欣赏艺术!很多爱好者问我如何提高自己的C语言编程水平,一口君不厌其烦地重复了同一句话:看Linux内核!代码免费且漂亮!代码自有金屋!我们必须像个女孩一样捡起内核!永远保持激情、任性和耐心!耐得住寂寞,每天看书,接她!从量变到质变!水滴穿石!希望大家都能熟练掌握Linux
