分享

解锁你对Linux内核的疑惑,让你成为一个更好的程序员!

 深度Linux 2023-07-14 发布于湖南
前言:小编热衷于收集整理资源,记录踩坑到爬坑的过程。希望能把自己所学,实际工作中使用的技术、学习方法、心得及踩过的一些坑,记录下来。也希望想做资深内核高级工程师的你一样,通过我的分享可以少走一些弯路,可以形成一套自己的方法,并应用到实际中。

学习Linux内核过程中,每个人都有自己的学习方法,仁者见仁智者见智。以下是我在学习过程中总结出来的东西,对自身来说,我认为比较有效率,拿出来跟大家交流一下。

为什么写这篇文章

刚开始学内核的时候,不要执着于一个方面,不要专注于一个子系统就一头扎到实际的代码行中去,因为这样的话,牵涉的面会很广,会碰到很多困难,容易产生挫败感,一个函数体中(假设刚开始的时候正在学习某个方面的某个具体的功能函数)很可能掺杂着其他各个子系统方面设计理念(多是大量相关的数据结构或者全局变量,用于支撑该子系统的管理工作)下相应的代码实现,这个时候看到这些东西,纷繁芜杂,是没有头绪而且很不理解的,会产生很多很多的疑问,(这个时候如果对这些疑问纠缠不清,刨根问底,那么事实上就是在学习当前子系统的过程中频繁的去涉足其他子系统,这时候注意力就分散了),而事实上等了解了各个子系统后再回头看这些东西的话,就简单多了,而且思路也会比较清晰。所以,要避免 “只见树木,不见森林”,不要急于深入到底层代码中去,不要过早研究底层代码。

我在大二的时候刚开始接触内核,就犯了这个错误,一头扎到内存管理里头,去看非常底层的实现代码,虽然也是建立在内存管理的设计思想的基础上,但是相对来说,比较孤立,因为此时并没有学习其它子系统,应该说无论是视野还是思想,都比较狭隘,所以代码中牵涉到的其它子系统的实现我都直接跳过了,这一点还算聪明,当然也是迫不得已的。

我的学习方法

刚开始,我认为主要的问题在于你知道不知道,而不是理解不理解,某个子系统的实现采用了某种策略、方法,而你在学习中需要做的就是知道有这么一回事儿,然后才是理解所描述的策略或者方法。

根据自己的学习经验,刚开始学习内核的时候,我认为要做的是在自己的脑海中建立起内核的大体框架,理解各个子系统的设计理念和构建思想,这些理念和思想会从宏观上呈现给你清晰的脉络,就像一个去除了枝枝叶叶的大树的主干,一目了然;当然,肯定还会涉及到具体的实现方法、函数,但是此时接触到的函数或者方法位于内核实现的较高的层次,是主(要)函数,已经了解到这些函数,针对的是哪些设计思想,实现了什么样的功能,达成了什么样的目的,混个脸熟的说法在这儿也是成立的。至于该主函数所调用的其它的辅助性函数就等同于枝枝叶叶了,不必太早就去深究。此时,也就初步建立起了内核子系统框架和代码实现之间的关联,关联其实很简单,比如一看到某个函数名字,就想起这个函数是针对哪个子系统的,实现了什么功能。

学习Linux内核要做好打持久战的准备,各个歼灭,稳扎稳打!信仰“如果你决定用十年的时间来学习LInux内核,那么可能用不了那么长时间就会成功。如果你决定用一年的时间来学习Linux内核,那么十年后你可能仍然什么都不精通。”

一、Linux内核简介

1.1什么是linux kernel?

内核(kernel)要负责资源管理:内存,io,cpu调度.此外,还有各种设备的驱动.内核还有两大基础组件:网络协议栈,文件系统。

内核是操作系统的核心组件,是计算机物理硬件与其上运行的进程之间的主要接口。内核通过提供对 CPU、内存、磁盘 I/O 和网络的访问,使多个应用程序能够共享硬件资源。 想象一台计算机由一系列层组成,最内层是硬件,最外层是运行在计算机上的软件应用程序。

在这个类比中,内核位于硬件和应用程序之间,因为它不仅负责管理硬件资源和执行软件程序,还负责监督这些层之间的交互。 现代计算机将内存划分为内核空间 和用户空间 。用户空间是执行应用软件的地方,而内核空间专用于运行计算机所需的幕后工作,如内存分配和进程管理。由于内核空间和用户空间的这种分离,内核所做的工作通常对用户是不可见的。

操作系统设计中,为减少系统本身的开销,往往将一些与硬件紧密相关的(如中断处理程序、设备驱动程序等)、基本的、公共的、运行频率较高的模块(如时钟管理、进程调度等)以及关键性数据结构独立开来,使之常驻内存,并对他们进行保护。通常把这一部分称之为操作系统的内核,也就是Kernel。

Linux 内核组成

Linux内核主要由5部分组成,分别为:进程调度(SCHED) 、内存管理(MMU) 、虚拟文件系统(VFS) 、网络接口(NET)和进程间通信(IPC)等 5 个子系统组成。

由系统调用层(系统调用子系统)进行统一管理,应用层通过系统调用层的函数接口与内核进行交互,用户应用程序执行的地方是用户空间,用户空间之下则是内核空间,Linux 内核正是位于内核空间中。

1.2Linux 内核的作用是什么?

内容有以下四项作用:

  1. 内存管理:追踪记录有多少内存存储了什么以及存储在哪里

  2. 进程管理:确定哪些进程可以使用中央处理器(CPU)、何时使用以及持续多长时间

  3. 设备驱动程序:充当硬件与进程之间的调解程序/解释程序

  4. 系统调用和安全防护:从流程接受服务请求

正确实现时,内核对用户是不可见的,它在自己的小世界(称为内核空间)中工作,从中分配内存,跟踪所有内容的存储位置。用户看到的东西(比如Web浏览器和文件)叫做用户空间。这些应用程序通过系统调用接口(SCI)与内核交互。

可以这样理解:内核就像一个忙碌的私人助理,为高管(硬件)服务。助理的工作是将员工和公众(用户)的信息和请求(流程)传递给高管,记住存储的内容和位置(内存),并确定谁可以在任何给定的时间访问高管,以及会议时间有多长。

1.3学习Linux内核准备工作

  1. 熟悉C语言,这个是最基本的

  2. 了解编译连接过程,如果写过ld、lcf类的链接文件最好,这样就能理解类似percpu变量的实现方法

  3. 学过或者自学过计算机组成原理或者微机原理,知道smp、cpu、cache、ram、hdd、bus的概念,明白中断、dma、寄存器,这样才能理解所谓的上下文context、barrier是什么。

Linux内核的特点:结合了unix操作系统的一些基础概念

Linux内核的任务:

  • 1.从技术层面讲,内核是硬件与软件之间的一个中间层。作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。

  • 2.从应用程序的层面讲,应用程序与硬件没有联系,只与内核有联系,内核是应用程序知道的层次中的最底层。在实际工作中内核抽象了相关细节。

  • 3.内核是一个资源管理程序。负责将可用的共享资源(CPU时间、磁盘空间、网络连接等)分配得到各个系统进程。

  • 4.内核就像一个库,提供了一组面向系统的命令。系统调用对于应用程序来说,就像调用普通函数一样。

内核实现策略:

1.微内核。最基本的功能由中央内核(微内核)实现。所有其他的功能都委托给一些独立进程,这些进程通过明确定义的通信接口与中心内核通信。

2.宏内核。内核的所有代码,包括子系统(如内存管理、文件管理、设备驱动程序)都打包到一个文件中。内核中的每一个函数都可以访问到内核中所有其他部分。目前支持模块的动态装卸(裁剪)。Linux内核就是基于这个策略实现的。

哪些地方用到了内核机制?

  • 1.进程(在cpu的虚拟内存中分配地址空间,各个进程的地址空间完全独立;同时执行的进程数最多不超过cpu数目)之间进行通 信,需要使用特定的内核机制。

  • 2.进程间切换(同时执行的进程数最多不超过cpu数目),也需要用到内核机制。

  • 进程切换也需要像FreeRTOS任务切换一样保存状态,并将进程置于闲置状态/恢复状态。

  • 3.进程的调度。确认哪个进程运行多长的时间。

Linux进程

  • 1.采用层次结构,每个进程都依赖于一个父进程。内核启动init程序作为第一个进程。该进程负责进一步的系统初始化操作。init进程是进程树的根,所有的进程都直接或者间接起源于该进程。

  • 2.通过pstree命令查询。实际上得系统第一个进程是systemd,而不是init(这也是疑问点)

  • 3.系统中每一个进程都有一个唯一标识符(ID),用户(或其他进程)可以使用ID来访问进程。

Linux内核源代码的目录结构

Linux内核源代码包括三个主要部分:

  1. 内核核心代码,包括第3章所描述的各个子系统和子模块,以及其它的支撑子系统,例如电源管理、Linux初始化等

  2. 其它非核心代码,例如库文件(因为Linux内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等

  3. 编译脚本、配置文件、帮助文档、版权说明等辅助性文件使用ls命令看到的内核源代码的顶层目录结构,具体描述如下。include/ ---- 内核头文件,需要提供给外部模块(例如用户空间代码)使用。

linux内核源代码目录结构:

  1. arch: 包含和硬件体系结构相关的代码,每种平台占一个相应的目录 如 i386、ARM、PowerPC、MIPS 等。

  2. block:块设备驱动程序 I/O 调度。

  3. crypto:常用加密和散列算法(如 AES、SHA 等) ,还有一些压缩和 CRC 校验算法。

  4. Documentation:内核各部分的通用解释和注释。

  5. drivers:设备驱动程序,每个不同的驱动占用一个子目录,如 char、block、net、mtd 、i2c 等。

  6. fs:支持的各种文件系统,如 EXT、F AT、NTFS、JFFS2 等。

  7. include:头文件,与系统相关的头文件被放置在 include/linux 子目录下。

  8. init:内核初始化代码。

  9. ipc:进程间通信的代码。kernel:内核的最核心部分,包括进程调度、定时器等,而和平台相关的一部分代码放在 arch/*/kernel 目录下。

  10. lib:库文件代码。

  11. mm:内存管理代码,和平台相关的一部分代码放在 arch/*/mm 目录下。

  12. net:网络相关代码,实现了各种常见的网络协议。

  13. scripts:包含用于配置内核的脚本文件。

  14. security:主要包含 SELinux 模块。

  15. sound:ALSA、OSS 音频设备的驱动核心代码和常用设备驱动。

  16. usr:实现了用于打包和压缩的 cpio 等。

二、Linux内核组成

2.1系统调用接口

SCI 层提供了某些机制执行从用户空间到内核的函数调用。正如前面讨论的一样,这个接口依赖于体系结构,甚至在相同的处理器家族内也是如此。SCI 实际上是一个非常有用的函数调用多路复用和多路分解服务。在 ./linux/kernel 中您可以找到 SCI 的实现,并在 ./linux/arch 中找到依赖于体系结构的部分。

2.2操作系统原理

操作系统(英语:Operating System,缩写:OS)是一组主管并控制计算机操作、运用和运行硬件、软件资源和提供公共服务来组织用户交互的相互关联的系统软件程序。根据运行的环境,操作系统可以分为桌面操作系统,手机操作系统,服务器操作系统,嵌入式操作系统等。

2.3进程管理子系统

进程管理的核心就是进程的调度。在 Linux 内核中,进程调度的单元是进程,进程调度控制系统中的多个进程对 CPU 的访问,从宏观上看,系统中的进程在 CPU 中是并发执行的。此外内核通过系统调用提供了应用程序编程接口,例如:创建新进程(fork,exec),结束进程(kill,exit),并且提供了控制进程,同步进程和进程间通信的接口。

进程管理还包括处理活动进程之间共享CPU的需求。内核实现了新的调度算法,无论多少个线程争夺CPU,都可以在固定的时间内运行。这种算法被称为O(1) scheduler,这意味着它调度多个线程所用的时间与调度一个线程所用的时间相同。O(1)调度器也可以支持多处理器(称为对称多处理器或SMP)。您可以在中找到流程管理的源代码。/linux/kernel,以及。/linux/arch。

进程调度子系统包括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,系统调用接口。进程调度子系统通过系统调用接口,将需要提供给用户空间的接口开放出去,同时屏蔽掉不需要用户空间程序关心的细节。

(1)进程与程序的区别:

  • 程序:存放在磁盘上的一系列代码和数据的可执行映像,是一个静止的实体。

  • 进程:是一个执行中的程序,它是动态的实体。

(2)进程的四要素:

  • 有一段程序供其执行,这段程序不一定是某个进程所专有,可以与其他进程共用。

  • 有进程专有的系统堆栈空间(也可以称之为内核堆栈空间)。

  • 在内核中有一个 task_struct 数据结构,即进程控制块。有了这个数据结构,进程才能被内核调度器识别并参与内核调度,除此之外它还记录着进程所占有的各项资源。

  • 除上述的专有的系统堆栈空间外,进程还需要有独立的用户堆栈空间,这就是 mm_struct 数据结构,该数据结构位于 task_struct 结构中,字段名称为 mm。

(3)进程的堆栈:

  • 内核在创建一个新的进程(创建进程控制块 task_struct) 时,为进程创建堆栈。

  • 一个进程有 2 个堆栈,即用户堆栈和系统堆栈;用户堆栈的空间指向用户地址空间,内核堆栈的空间指向内核地址空间。

  • 当进程在用户态运行时,CPU 堆栈指针寄存器指向用户堆栈地址,使用用户堆栈。

  • 当进程运行在内核态时,CPU 堆栈指针寄存器指向的是内核堆栈空间地址,使用内核堆栈。

(4)进程与线程的区分:

  • 进程:四个要素是必要条件

  • 用户线程:有共享的用户空间

  • 内核线程:没有用户空间,即 mm_struct 为 NULL

简单区分如图所示:

(5)进程调度:

  • 进程调度是进程管理子系统中最重要的一个功能,是一个管理进程之间使用 CPU 资源的管理程序。

  • 进程调度器有效地为各个进程分配其使用的 CPU 资源时间,同时又要达到良好的用户体验效果,此外调度器还需要解决一些互相冲突的情况,例如既要实现实时任务的最小化响应时间, 又要最大限度地提高 CPU的总体利用率等。

  • 在 Linux2.6 版本之后,进程调度器使用新的进程调度算法——Completely Fair Scheduler,简称 CFS,即完全公平调度算法。该算法会按所需分配的计算能力,向系统中每个进程提供最大的公正性,它负责将 CPU 资源,分配给正在执行的进程,目标在于最大化程式互动效能,最小化整体 CPU 的运用,这个算法使用红黑树来实现,算法效率为 O(log(n))。

(6)进程状态:

2.4内存管理子系统

主要作用是保证系统安全访问内存区域,且绝大部分 CPU 都是支持内存管理单元的(Memory Management Unit,MMU)

内存管理子系统负责管理每个进程完成从虚拟内存到物理内存的转换,以及系统可用内存空间。

内存管理的硬件按照分页方式管理内存,分页就是把系统的物理内存按照相同大小等分,每个内存分片称作内存页,通常内存页大小是 4KB。内存管理子系统要管理的不仅是 4KB 缓冲区,它提供了对 4KB 缓冲区的抽象,例如 slab 分配器。这种内存管理模式使用 4KB 缓冲区为基数,然后从中分配管理结构,并跟踪内存页使用情况。系统就支持动态调整内存使用情况。

Linux 还支持内存交换,因为 Linux 中使用的是虚拟内存,当物理内存不足时,内存管理子系统会将内存暂时移到磁盘中,在物理内存充裕时又将内存页从磁盘移到物理内存中。

在 32 位的系统上,每个进程都最大享有 4GB 的内存空间,因为由于 32 位的系统寻址空间只有4G,当然这是虚拟内存,0~3GB 是属于用户内存空间,3~4GB 是属于系统内存空间,实际上用户的程序几乎使用不完那么大的用户空间,一旦超出将无法正常运行,当然系统内存空间与用户内存空间是可以调整的。

内存管理主要提供对内存资源的访问控制。Linux系统会在硬件物理内存和进程所使用的内存(称作虚拟内存)之间建立一种映射关系,这种映射是以进程为单位,因而不同的进程可以使用相同的虚拟内存,而这些相同的虚拟内存,可以映射到不同的物理内存上。

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

(1)Architecture Specific Managers,体系结构相关部分。提供用于访问硬件Memory的虚拟接口。

(2)Architecture Independent Manager,体系结构无关部分。提供所有的内存管理机制,包括:以进程为单位的memory mapping;虚拟内存的Swapping。

(3)System Call Interface,系统调用接口。通过该接口,向用户空间程序应用程序提供内存的分配、释放,文件的map等功能。

2.5文件管理子系统

在 Linux 系统中一切皆文件,它把一切资源都看作是文件,包括硬件设备,通常称为设备文件。

Linux 的文件管理子系统主要实现了虚拟文件系统(Virtual File System,VFS),虚拟文件系统屏蔽了各种硬件上的差异以及具体实现的细节,为所有的硬件设备提供统一的接口,即实现了设备无关性,同时文件管理系统还为应用层提供统一的 API 接口。

Linux 的文件系统体系结构是对一个对复杂系统进行了抽象化,通过使用一组通用的 API 函数,Linux 可以在许多种存储设备上支持多种文件系统,如 NTFS、EXT2、EXT3、EXT4 、FAT 等等;而用户空间包含一些应用程序和 GNU C 库(glibc),它们使用的 API 接口是由系统调用层提供(如打开、读、写和关闭等)。

文件系统的实质,就是“存储和组织数据的方法”,文件系统的表现形式,就是“从某个设备中读取数据和向某个设备写入数据”。常见文件系统的类型 :FAT、FAT32、NTFS、EXT2、EXT3,EXT4 。而为了兼容,操作系统或者内核,要以相同的表现形式,同时支持多种类型的文件系统,这就延伸出了虚拟文件系统(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,该模块负责以统一的接口(快设备和字符设备)表示硬件设备和逻辑文件系统,这样上层软件就不再关心具体的硬件形态了。
3.5) System Call Interface,系统调用接口,向用户空间提供访问文件系统和硬件设备的统一的接口。

2.6网络子系统

在 Linux 内核中,与网络相关的代码被 Linux 独立开,形成一个相对独立的子系统,称为网络子系统,网络子系统是一个层次化的结构,可分为以下几个层次:

  • Socket 层(也可以称之为协议无关层):Linux 在发展过程中,采用 BSD Socket API 作为自己的网络相关的 API 接口。同时,Linux 的目标又要能支持各种不同的协议族,而且这些协议族都可以使用 BSD Socket API 作为应用层的编程接口,这样一来将 Socket 层抽象出来就能屏蔽不同协议族之间的差异,不会对应用层的使用产生影响。

  • 协议层:Linux 网络子系统功能上相当完备,它不仅支持 INET 协议族(也就是通常所说的 TCP/IP 协议族),而且还支持其它很多种协议族,如 INET6、DECnet,ROSE,NETBEUI 等,对于 INET 、INET6 协议族来说,又会进一步将协议族划分为传输层和网络层以及链路层等。

  • 网络设备层:网络设备其实是设备驱动层的内容了,它抽象了网卡数据结构,在一个系统中可能存在多种网卡,屏蔽了不同硬件上的差异,这一层提供了一组通用函数供底层网络设备驱动程序使用。

Network,网络子系统。负责管理系统的网络设备,并实现多种多样的网络标准。网络子系统在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(Inter-Process Communication),进程间通信。IPC不管理任何的硬件,它主要负责Linux系统中进程之间的通信。

2.7设备子系统

设备子系统又被称之为设备驱动,如 LCD、摄像头、USB、音频等都是属于设备,且设备的厂商不同其驱动程序也是不同的,但是对于 Linux 来说,不可能去将每个设备都包含到内核,它只能抽象去描述某种设备。

系统调用层是 Linux 内核与应用程序之间的接口,而设备驱动则是 Linux 内核与硬件之间的接口,设备驱动程序为应用程序屏蔽了硬件的细节,在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作(打开、读、写和关闭)。

设备驱动程序是内核的一部分,主要功能:

  • 对设备初始化和释放

  • 把数据从内核传送到硬件和从硬件读取数据

  • 读取应用程序传送给设备文件的数据和回送应用程序请求的数据

  • 检测和处理设备出现的错误

根据设备的共性将设备分类:字符设备、块设备、网络设备

  • 字符设备,是以字节为单位传输的 IO 设备,可以提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。这种字符传输的效率通常是比较低的,如鼠标、键盘、串口等都是字符设备。

  • 块设备,是以块为单位进行传输的设备,应用程序可以随机访问块设备中的数据,程序可以指定读取数据的位置。磁盘就是一种常见的块设备,应用程序可以寻址磁盘上的任何位置,并在这个位置读取数据。块设备读取的数据只能以块为单位的倍数进行(通常是 512Byte 的整数倍),而不能与字符设备一样以字节为单位读取。块设备的传输速度是比较高的。

  • 网络设备,其实就是网络子系统中描述的网络设备层,统一描述了不同的网卡设备,如 WIFI、以太网等。因为网络设备存在协议栈(协议族),它涉及了网络层协议,所以 Linux 将网络设备单独分层一类设备。传输速率通常很高。

2.8网络堆栈

网络堆栈的设计遵循模拟协议本身的分层架构。回想一下,互联网协议(IP)是传输协议(通常称为传输控制协议或TCP)下的核心网络层协议。TCP是上面的套接字层,通过SCI调用。套接字层是网络子系统的标准API,它为各种网络协议提供了一个用户接口。从原始帧访问到IP协议数据单元(PDU),再到TCP和用户数据报协议(UDP),套接字层提供了一种标准化的方式来管理连接并在各种端点之间移动数据。内核网络源代码可以在。/linux/net。

2.9设备驱动程序

Linux内核很多代码都在设备驱动里,可以运行特定的硬件设备。Linux源码树提供了一个驱动子目录,该子目录又进一步划分为各种支持设备,如蓝牙、I2C、串口等。设备驱动程序的代码可以在。/Linux/驱动程序。

2.10依赖体系结构的代码

虽然Linux很大程度上独立于运行的架构,但为了正常运行和实现更高的效率,一些元素必须考虑架构。的。/linux/arch子目录定义了内核源代码中依赖于架构的部分,其中包含了各种特定于架构的子目录(它们共同构成了BSP)。对于典型的桌面系统,使用x86目录。每个架构子目录包含许多其他子目录,每个子目录专注于内核的特定方面,如引导、内核、内存管理等。这些依赖于架构的代码可以在。/linux/arch。

如果Linux内核的可移植性和效率不够好的话,Linux还提供了一些其他的特性,不能归入以上几类。作为生产操作系统和开源软件,Linux是测试新协议及其增强的良好平台。Linux支持大量的网络协议,包括典型的TCP/IP,以及高速网络的扩展(大于1千兆以太网[GbE]和10 GbE)。Linux还可以支持诸如流控制传输协议(SCTP)之类的协议,它提供了比TCP更高级的特性(它是传输层协议的继承者)。Linux也是一个动态内核,支持动态添加或删除软件组件。它们被称为可动态加载的内核模块,可以由用户根据需要在引导时插入(目前,一个特定的设备需要这个模块),也可以在任何时候插入。Linux的最新增强是可以作为其他操作系统使用的操作系统(称为hypervisor)。最近,内核被修改并被称为基于内核的虚拟机(KVM)。这一修改为用户空间启用了一个新的接口,允许其他操作系统在启用KVM的内核上运行。除了运行Linux的其他实例,Microsoft Windows也可以虚拟化。唯一的限制是底层处理器必须支持新的虚拟化指令。

2.11依赖体系结构的代码

虽然Linux很大程度上独立于运行的架构,但为了正常运行和实现更高的效率,一些元素必须考虑架构。的。/linux/arch子目录定义了内核源代码中依赖于架构的部分,其中包含了各种特定于架构的子目录(它们共同构成了BSP)。对于典型的桌面系统,使用x86目录。每个架构子目录包含许多其他子目录,每个子目录专注于内核的特定方面,如引导、内核、内存管理等。这些依赖于架构的代码可以在。/linux/arch。

如果Linux内核的可移植性和效率不够好的话,Linux还提供了一些其他的特性,不能归入以上几类。作为生产操作系统和开源软件,Linux是测试新协议及其增强的良好平台。Linux支持大量的网络协议,包括典型的TCP/IP,以及高速网络的扩展(大于1千兆以太网[GbE]和10 GbE)。Linux还可以支持诸如流控制传输协议(SCTP)之类的协议,它提供了比TCP更高级的特性(它是传输层协议的继承者)。Linux也是一个动态内核,支持动态添加或删除软件组件。它们被称为可动态加载的内核模块,可以由用户根据需要在引导时插入(目前,一个特定的设备需要这个模块),也可以在任何时候插入。Linux的最新增强是可以作为其他操作系统使用的操作系统(称为hypervisor)。最近,内核被修改并被称为基于内核的虚拟机(KVM)。这一修改为用户空间启用了一个新的接口,允许其他操作系统在启用KVM的内核上运行。除了运行Linux的其他实例,Microsoft Windows也可以虚拟化。唯一的限制是底层处理器必须支持新的虚拟化指令。

2.12内核书籍

  • 《深入了解Linux内核》

  • 《Linux就该这么学》

  • 《Linux内核完全注释V3.0书签版》

  • 《Linux命令行大全 - 绍茨 (william E.shotts)》

  • 《Linux命令速查手册》

  • 《Linux性能优化大师》

  • 《Linux环境编程:从应用到内核》

  • 《Linux集群和自动化运维 余洪春》

  • 《Linux驱动程序开发实例(第2版)》

  • 《Linux高级程序设计(第3版)》

  • 《构建高可用Linux服务器(第4版)》

三、目标与定位

先有目标,再去定位。学内核,从硬件上讲,一方面就是学习接学习CPU、主板、内存等硬件的基本原理和工作方式,了解它们之间的交互,另一方面就是学习了解进程、线程、文件系统、网络等操作系统的基本概念和实现原理。如果从软件上讲,就是要学习C语言,C语言是Linux内核最常用的编程语言,因此熟练掌握C语言对于学习内核非常重要。

这些对于初学都来说必须明确,要么从硬件着手开始学,要么从操作系统的熟悉到应用开始学,但不管学什么,只要不是纯的操作系统应用层的编程,硬件的寄存器类的东西还是要能看懂的。因此阅读Linux或其他开源操作系统的内核代码是最好的学习方法之一。可以从简单的驱动程序开始,逐步深入到更复杂的部分。

3.1为什么要学习 Linux 内核

大部分程序员可能永远没有机会开发Linux内核或者驱动Linux,那么我们为什么还需要学习Linux内核呢?Linux的源代码和架构都是开放的,我们可以学到很多操作系统的概念和实现原理。Linux的设计哲学体系继承了UNIX,现在整个设计体系相当稳定和简化,这是大部分服务器使用Linux的重要原因。

那学习Linux内核的原因就在于此。

进一步了解内核的原理,有助于你更好地使用命令和程序设计,让你的面试和开发更上一层楼。但是不建议直接看源代码,因为Linux代码太大,容易丢失。

而最好的办法是,先了解一下Linux内核机制,知道基本的原理与流程。

不过,Linux内核机制也非常复杂,而且其中互相关联。

比如说,进程运行要分配内存,内存映射涉及文件的关联,文件的读写需要经过块设备,从文件中加载代码才能运行起来进程。这些知识点要反复对照,才能理清。

但是一旦攻克!你会发现Linux这个复杂的系统开始透明起来。

2.3怎么阅读源码?

内核的知识就像下面的绳结一样,一环扣一环,我们要解开它们,就必须要先找到线头也就是内核中的函数接口。初学阶段,我们一般不深入的研究内核代码,会使用内核的接口函数就不错了。

Linux庞大而复杂,其核心包括进程管理、内存管理、网络、文件系统和arch-entity="2 " >驱动,这些都依赖于内核提供的各种库和接口、各种内核机制以及arch下可能对应的汇编。没有这些基础,要流畅的阅读代码就有点困难了。

Linux的代码量很大,而且是在gcc的基础上开发的,针对各种场景做了大量的优化。所以第二件事就是要熟悉gcc下C的扩展用法,要有一个好的代码查看工具。推荐源洞察。

内核运行在特定的硬件平台上,所以对于底层涉及的部分有不同的arch实现,包括大量的汇编操作,所以以arm为例。如果想研究内核相应部分的代码,就必须多读,熟悉arm的官方文档。

而且代码和资料基本都是英文的,一般词汇和专业词汇都有,所以英语基础好很重要。这个没有捷径,就是多读书,当然也有积累的方法,后面会讲到。

每个模块都有很多细节。可能你年轻的时候记性好吧。你开发一个模块的时候,都读了好几遍了,所有的细节都不是很清楚。可能3、5年后再看就很难记住了,所以需要想办法形成积累。否则可能会忘记看,辛苦又低效。

内核编程有自己的风格和一些公认的规则,尤其是命名、排版、代码文件分类等。有些可能不符合规则,也可能很好,但如果大家都这样用,那自然就是所谓的艺术了,熟悉这些艺术有助于举一反三的学习其他模块的代码。

内核的代码量与日俱增,模块也越来越复杂,所以可维护性对于内核来说也是非常重要的。所以在如何更有利于以后的维护上做了很多努力。内核是操作系统的核心部分,其稳定性和性能自然非常重要。它用了很多技巧来应对。研究这些,积累起来,有利于进一步理解其原理。

边看代码边写注释和笔记。看了多少模块就注释多少模块,慢慢形成一个积累。这样的方式有什么好处呢?

  1. 记录你看代码过程中不熟悉或者不清晰的地方,或者你看明白了但是怕忘记的地方,这样等你下次再来看你能很快回忆起来,且不断刺激你的记忆神经能让你记忆的更牢固。

  2. 记录内核中用法的好处或者有疑问的地方,这样你再次来看的话可能会有新的体会,能在之前看代码的基础上形成一个不断积累的过程,理解会更加深刻。

  3. 当你将内核代码模块看的越来越多时,你会越看越轻松,当然是不是也会惊讶一下。轻松的是这个模块我看过,用法我熟悉,惊讶的是这个我虽然看过好多次,理解竟然有点不对。反反复复不断进行下去。

查看代码的工具

我这里推荐是source insight, 我一直用的3.5版本的。这里主要提几点技巧。

3.5里面默认只支持一部分文件格式,那么比如makefile是不支持的,arm汇编是不支持的,shell好像也是不支持的,所以这一部分的支持要自己添加。

内核里面用了大量的宏以及一些gnu c的扩展关键字,这些需要在source insight里面添加 上,这样你同步代码就不会有一些不认识的情况,当然除了source insight本身的一些bug外。

source insight自建快捷键以及扩展功能,这些网上也有很多好的,可以参考,能提高效率。

3.3Linux内核学习路线

学习linux内核不像学习语言。一个月或者三月就能掌握C或者java。学习linux内核需要循序渐进,掌握正确的linux内核学习路线非常重要。本文将分享一些学习linux内核的建议。

很多同学接触Linux不多,对Linux平台的开发更是一无所知。而现在的趋势越来越表明,作为一 个优秀的软件开发人员,或计算机IT行业从业人员,掌握Linux是一种很重要的谋生资源与手段。下来我将会结合自己的几年的个人开发经验,及对 Linux,更是类UNIX系统,及开源软件文化,谈谈Linux的学习方法与学习中应该注意的一些事。

就如同刚才说的,很多同学以前可能连Linux是什么都不知道,对UNIX更是一无所知。所以我们从最基础的讲起,对于Linux及UNIX的历史我们不做多谈,直接进入入门的学习。

Linux入门是很简单的,问题是你是否有耐心,是否爱折腾,是否不排斥重装一类的大修。没折腾可以说是学不好Linux的,鸟哥说过,要真正了解Linux的分区机制,对LVM使用相当熟练,没有20次以上的Linux装机经验是积累不起来的,所以一定不要怕折腾。

由于大家之前都使用Windows,所以我也尽可能照顾这些“菜鸟”。我的推荐,如果你第一次接触Linux,那么首先在虚拟机中尝试它。虚拟机我推荐Virtual Box,我并不主张使用VM,原因是VM是闭源的,并且是收费的,我不希望推动盗版。当然如果你的Money足够多,可以尝试VM,但我要说的是即使是VM,不一定就一定好。付费的软件不一定好。首先,Virtual Box很小巧,Windows平台下安装包在80MB左右,而VM动辄600MB,虽然功能强大,但资源消耗也多,何况你的需求Virtual Box完全能够满足。所以,还是自己选。如何使用虚拟机,是你的事,这个我不教你,因为很简单,不会的话Google或Baidu都可以,英文好的可以直接看官方文档。

现在介绍Linux发行版的知识。正如你所见,Linux发行版并非Linux,Linux仅是指操作系统的内核,作为科班出生的你不要让我解释,我也没时间。

我推荐的发行版如下:

  1. UBUNTU适合纯菜鸟,追求稳定的官方支持,对系统稳定性要求较弱,喜欢最新应用,相对来说不太喜欢折腾的开发者。

  2. Debian,相对UBUNTU难很多的发行版,突出特点是稳定与容易使用的包管理系统,缺点是企业支持不足,为社区开发驱动。

  3. Arch,追逐时尚的开发者的首选,优点是包更新相当快,无缝升级,一次安装基本可以一直运作下去,没有如UBUNTU那样的版本概念,说的专业点叫滚动升级,保持你的系统一定是最新的。缺点显然易见,不稳定。同时安装配置相对Debian再麻烦点。

  4. Gentoo,相对Arch再难点,考验使用者的综合水平,从系统安装到微调,内核编译都亲历亲为,是高手及黑客显示自己技术手段,按需配置符合自己要求的系统的首选。

Slackware与Gentoo类似:

CentOS,社区维护的RedHat的复刻版本,完全使用RedHat的源码重新编译生成,与RedHat的兼容性在理论上来说是最好的。如果你专注于Linux服务器,如网络管理,架站,那么CentOS是你的选择。

LFS,终极黑客显摆工具,完全从源代码安装,编译系统。安装前你得到的只有一份文档,你要做的就是照文档你的说明,一步步,一条条命令,一个个软件包的去构建你的Linux,完全由你自己控制,想要什么就是什么。如果你做出了LFS,证明你的Linux功底已经相当不错,如果你能拿LFS文档活学活用,再将Linux从源代码开始移植到嵌入式系统,我敢说中国的企业你可以混的很好。

你得挑一个适合你的系统,然后在虚拟机安装它,开始使用它。如果你想快速学会Linux,我有一个建议就是忘记图形界面,不要想图形界面能不能提供你问题的答案,而是满世界的去找,去问,如何用命令行解决你的问题。在这个过程中,你最好能将Linux的命令掌握的不错,起码常用的命令得知道,同时建立了自己的知识库,里面是你积累的各项知识。

再下个阶段,你需要学习的是Linux平台的C++/C++开发,同时还有Bash脚本编程,如果你对Java兴趣很深还有Java。同样,建议你抛弃掉图形界面的IDE,从VIM开始,为什么是VIM,而不是Emacs,我无意挑起编辑器大战,但我觉得VIM适合初学者,适合手比较笨,脑袋比较慢的开发者。Emacs的键位太多,太复杂,我很畏惧。然后是GCC,Make,Eclipse(Java,C++或者)。虽然将C++列在了Eclipse中,但我并不推荐用IDE开发C++,因为这不是Linux的文化,容易让你忽略一些你应该注意的问题。IDE让你变懒,懒得跟猪一样。如果你对程序调试,测试工作很感兴趣,GDB也得学的很好,如果不是GDB也是必修课。可以参考这篇文章——看懂GDB调试核心:剖析ptrace原理及其应用场景!

这是开发的第一步,注意我并没有提过一句Linux系统API的内容,这个阶段也不要关心这个。你要做的就是积累经验,在Linux平台的开发经验。我推荐的书如下:C语言程序设计,谭浩强的也可以。C语言,白皮书当然更好。C++推荐C++ Primer Plus,Java我不喜欢,就不推荐了。工具方面推荐VIM的官方手册,GCC中文文档,GDB中文文档,GNU开源软件开发指导(电子书),汇编语言程序设计(让你对库,链接,内嵌汇编,编译器优化选项有初步了解,不必深度)。

如果你这个阶段过不了就不必往下做了,这是底线,最基础的基础,否则离开,不要霍霍Linux开发。不专业的Linux开发者作出的程序是与Linux文化或UNIX文化相背的,程序是走不远的,不可能像Bash,VIM这些神品一样。所以做不好干脆离开。

接下来进入Linux系统编程,不二选择,APUE,UNIX环境高级编程,一遍一遍的看,看10遍都嫌少,如果你可以在大学将这本书翻烂,里面的内容都实践过,有作品,你口头表达能力够强,你可以在面试时说服所有的考官。(可能有点夸张,但APUE绝对是圣经一般的读物,即使是Windows程序员也从其中汲取养分,Google创始人的案头书籍,扎尔伯克的床头读物。)

这本书看完后你会对Linux系统编程有相当的了解,知道Linux与Windows平台间开发的差异在哪?它们的优缺点在哪?我的总结如下:做Windows平台开发,很苦,微软的系统API总在扩容,想使用最新潮,最高效的功能,最适合当前流行系统的功能你必须时刻学习。Linux不是,Linux系统的核心API就100来个,记忆力好完全可以背下来。而且经久不变,为什么不变,因为要同UNIX兼容,符合POSIX标准。所以Linux平台的开发大多是专注于底层的或服务器编程。这是其优点,当然图形是Linux的软肋,但我站在一个开发者的角度,我无所谓,因为命令行我也可以适应,如果有更好的图形界面我就当作恩赐吧。

另外,Windows闭源,系统做了什么你更本不知道,永远被微软牵着鼻子跑,想想如果微软说Win8不支持QQ,那腾讯不得哭死。而Linux完全开源,你不喜欢,可以自己改,只要你技术够。另外,Windows虽然使用的人多,但使用场合单一,专注与桌面。而Linux在各个方面都有发展,尤其在云计算,服务器软件,嵌入式领域,企业级应用上有广大前景,而且兼容性一流,由于支持POSIX可以无缝的运行在UNIX系统之上,不管是苹果的Mac还是IBM的AS400系列,都是完全支持的。另外,Linux的开发环境支持也绝对是一流的,不管是C/C++,Java,Bash,Python,PHP,Javascript,。。。。。。就连C#也支持。而微软除Visual Stdio套件以外,都不怎么友好,不是吗?

如果你看完APUE的感触有很多,希望验证你的某些想法或经验,推荐UNIX程序设计艺术,世界顶级黑客将同你分享他的看法。现在是时候做分流了。 大体上我分为四个方向:网络,图形,嵌入式,设备驱动。

如果选择网络,再细分,我对其他的不是他熟悉,只说服务器软件编写及高性能的并发程序编写吧。相对来说这是网络编程中技术含量最高的,也是底层的。需要很多的经验,看很多的书,做很多的项目。

我的看法是以下面的顺序来看书:

  1. APUE再深读 – 尤其是进程,线程,IPC,套接字

  2. 多核程序设计 - Pthread一定得吃透了,你很NB

  3. UNIX网络编程 – 卷一,卷二

  4. TCP/IP网络详解 – 卷一 再看上面两本书时就该看了

  5. TCP/IP 网络详解 – 卷二 我觉得看到卷二就差不多了,当然卷三看了更好,努力,争取看了

  6. Lighttpd源代码 - 这个服务器也很有名了

  7. Nginx源代码 – 相较于Apache,Nginx的源码较少,如果能看个大致,很NB。看源代码主要是要学习里面的套接字编程及并发控制,想想都激动。如果你有这些本事,可以试着往暴雪投简历,为他们写服务器后台,想一想全球的魔兽都运行在你的服务器软件上。

  8. Linux内核TCP/IP协议栈 – 深入了解TCP/IP的实现

如果你还喜欢驱动程序设计,可以看看更底层的协议,如链路层的,写什么路由器,网卡,网络设备的驱动及嵌入式系统软件应该也不成问题了。当然一般的网络公司,就算百度级别的也该毫不犹豫的雇用你。只是看后面这些书需要时间与经验,所以35岁以前办到吧!跳槽到给你未来的地方!

图形方向,我觉得图形方向也是很有前途的,以下几个方面:

Opengl的工业及游戏开发,国外较成熟。

影视动画特效,如皮克斯,也是国外较成熟。

GPU计算技术,可以应用在浏览器网页渲染上,GPU计算资源利用上,由于开源的原因,有很多的文档程序可以参考。如果能进火狐开发,或google做浏览器开发,应该会很好 。

嵌入式方向:嵌入式方向没说的,Linux很重要

掌握多个架构,不仅X86的,ARM的,单片机什么的也必须得懂。硬件不懂我预见你会死在半路上,我也想走嵌入式方向,但我觉得就学校教授嵌入式的方法,我连学电子的那帮学生都竞争不过。奉劝大家,一定得懂硬件再去做,如果走到嵌入式应用开发,只能祝你好运,不要碰上像Nokia,Hp这样的公司,否则你会很惨的。

驱动程序设计:软件开发周期是很长的,硬件不同,很快。每个月诞生那么多的新硬件,如何让他们在Linux上工作起来,这是你的工作。由于Linux的兼容性很好,如果不是太低层的驱动,基本C语言就可以搞定,系统架构的影响不大,因为有系统支持,你可能做些许更改就可以在ARM上使用PC的硬件了,所以做硬件驱动开发不像嵌入式,对硬件知识的要求很高。可以从事的方向也很多,如家电啊,特别是如索尼,日立,希捷,富士康这样的厂子,很稀缺的。

内核是IT开发人员的加分项,一个计算机系统是一个硬件和软件的共生体,它们互相依赖,不可分割。计算机的硬件,含有外围设备、处理器、内存、硬盘和其他的电子设备组成计算机的发动机。但是没有软件来操作和控制它,自身是不能工作的。完成这个控制工作的软件就称为操作系统,在Linux的术语中被称为“内核”,也可以称为“核心”。Linux内核的主要模块(或组件)分以下几个部分:存储管理、CPU和进程管理、文件系统、设备管理和驱动、网络通信,以及系统的初始化(引导)、系统调用等。

Linux 内核实现了很多重要的体系结构属性。在或高或低的层次上,内核被划分为多个子系统。Linux 也可以看作是一个整体,因为它会将所有这些基本服务都集成到内核中。这与微内核的体系结构不同,后者会提供一些基本的服务,例如通信、I/O、内存和进程管理,更具体的服务都是插入到微内核层中的。

随着时间的流逝,Linux 内核在内存和 CPU 使用方面具有较高的效率,并且非常稳定。但是对于 Linux 来说,最为有趣的是在这种大小和复杂性的前提下,依然具有良好的可移植性。Linux 编译后可在大量处理器和具有不同体系结构约束和需求的平台上运行。一个例子是 Linux 可以在一个具有内存管理单元(MMU)的处理器上运行,也可以在那些不提供MMU的处理器上运行。Linux 内核的uClinux移植提供了对非 MMU 的支持。

在IT行业 如:嵌入式开发,驱动开发,Android开发,c++开发,Java开发如果接触到底层方面 那么 懂得内核:会使自己的开发工作产生对应的效益。 懂得内核:会让自己更加了解底层的原理与开发源码。 内核是面试的加分项 内核是走向专家的必经之路 不管你是不是做内核开发,内核技术是储备技能,开阔视野,扩展技术面的不二选择。

要转向内核开发,嵌入式开发人员需要掌握以下知识:

  • 1. C语言编程:C语言是内核开发的主要编程语言,需要熟练掌握其语法和编程技巧。

  • 2. 操作系统原理:需要了解操作系统的基本原理,包括进程管理、内存管理、文件系统等。

  • 3. Linux内核:需要深入了解Linux内核的架构、模块、驱动程序等。

  • 4. 设备驱动开发:需要掌握设备驱动的开发流程和技术,包括字符设备、块设备、网络设备等。

  • 5. 调试技能:需要掌握调试技能,包括使用调试工具、分析内核崩溃等。

  • 6. 硬件知识:需要了解硬件的基本原理和操作,包括处理器、内存、外设等。

  • 7. 开源社区:需要了解开源社区的文化和开发流程,以便更好地参与内核开发。

  • 总之,转向内核开发需要广泛的知识储备和实践经验,需要不断学习和探索。

内核学习路线推荐,喜欢研究内核,想在内核这块深入学习的,可以参考。

  • 操作系统原理/汇编专题

    1:操作系统原理 进程管理:进程状态与切换、进程互斥与同步、处理器调度、进程死锁 内存管理 :存储结构、分区存储管理、段式管理、页式管理、虚拟存储 设备管理:磁盘高速缓存、RAID(磁盘阵列)、I/O缓冲 文件管理:文件组织结构、堆文件原理、存储空间管理、文件目录管理 2:汇编语言精讲 x86/x86_64体系结构:x86/x86_64体系结构、汇编语言基础、数据传送、算法运算、寻址、过程与条件处理、浮点处理与指令编码 ARM体系结构:ARM核微处理器、ARM常用指令系统、ARM汇编程序及调试、异常中断/复位处理程序/SWI异常中断、RealView MDK安装与配置、ARM汇编与C混合实现、数据加载与存储指令实现

  • 进程管理专题

    1:进程基础 Linux内核源码组织结构 进程原理及进程状态 生命周期及系统调用:写时复制原理、进程内存布局、进程堆栈管理、系统调用实现 task_struct数据结构分析 2 :进程调度 调度策略:SCHED_DEADLINE、SCHED_FIFO、SCHED_RR、SCHED_NORMAL 进程优先级:调度优先级、静态优先级、正常优先级、实时优先级 调度类分析:stop_sched_class、dl_sched_class、rt_sched_class、cfs_sched_class、idle_shced_class SMP调度:迁移线程/隔离处理器、限期调度类的处理器负载均衡、实时调度类的处理器负载均衡、公平调度类的处理器负载均衡

  • 内存管理专题

    1:内存原理 SMP/NUMA模型组织 物理内存组织结构与模型 页表/页表缓存:页表框架目录结构、TLB表项格式与管理、地址空间标识符(ASID)、虚拟机标识符(VMID) 处理器缓存:缓存结构与策略、SMP缓存一致性、高速缓存与TLB控制 内存映射:数据结构分析、创建内存映射、删除内存映射、系统调用实现 2:虚拟内存 块分配器:内存分配器原理、页分配与页释放、SLAB块分配器、SLOB块分配器、SLUB块分配器、系统调度接口 页模块大全:标准巨型页、透明巨型页、LRU算法与反向映射、页直接与异步回收原理、回收不活动页执行方案、页交换原理、回收slab缓存原理、页错误异常处理、内存碎片整理、发起内存回收、交换区数据结构/创建/激活、内存耗尽技术原理、缺页异常校正方法、KASAN检测工具、处理交换缺页异常、内存屏障与内核互斥技术。 3:内存系统调用 kmalloc/vmalloc 内存池原理与实现操作 内存优化参数与实现 页缓存的实现 块缓存的实现 4: perf性能分析工具 perf原理机制与安装配置 perf采集数据命令29种工具应用 perf采集数据至火焰图分析

  • 网络协议栈专题

    1: 网络基础架构 ICMP协议 用户数据报协议(UDP) 传输控制协议(TCP) 流控制传输协议(SCTP) 数据报拥塞控制协议(DCCP) IPv4策略路由选择 无线子系统模块:802.11 MAC帧结构分析、扫描/身份验证/关联、mac80211接收与传输实现、高吞吐量(802.11n)、网状网络(802.11s) IPv4重定向消息/FIB表 2:网络协议栈 ARP(地址解析协议) 用户数据报协议(UDP) 传输控制协议(TCP) 高级路由选择:组播路由选择、策略路由选择、多路径路由选择 接收/发送IPv4数据包 接收/发送IPv6数据包 InfiniBand栈的架构:RDMA(远程直接内存访问 )结构、InfiniBand组件与编址、InfiniBand功能与数据包 协议栈注册/接收包/发送包流程方案 3:系统API调用 POSIX网络API调用 epoll内核原理与实现 网络系统参数配置

  • 设备驱动专题

    1:设备驱动子系统 I/O机制原理 资源分配与管理 字符设备子系统 块设备子系统 网络接口卡驱动 2: Linux设备模型 深度剖析LDM:LDM数据结构、设备驱动程、kobject结构、kobj_type、内核对象集合 设备模型和sysfs:sysfs文件及属性、允许轮询sysfs属性文件、 3:字符设备操作 主设备与次设备 打开设备文件 分配与注册字符设备 写文件操作实现:open/release方法、read/write方法、llseek/poll方、填充file_operations结构 插入和删除模块 4: 块设备操作 块设备表示与数据结构 BIO数据结构 ioctl系统调用 总线模块: ISA总线、PCI/PCI-E总线、USB总线、VESA总线、I2C总线 5: 网卡设备驱动 数据结构:套接字缓冲区结构、网络接口结构 缓冲区管理与并发控制 ISA网络驱动程序 ATM异步传输模式 网络吞吐量

  • 内核组件专题

    1:时间管理 通用时间子系统 高分辨率定时器 动态时钟数据结构 定时器系统调用 2:页与块缓存 页缓存结构操作与实现 块缓存结构与实现 地址空间数据结构与页树 3:数据同步 数制同步机制 inode同步与拥塞 强制回写与完全同步 4:内核活动 中断类型/硬件IRQ irq_desc数据结构 处理IRQ与软中断 创建/注册/执行tasklet 等待队列与完成量

  • 文件系统专题

    1:虚拟文件系统VFS 文件系统类型与文件模型研究 数据结构:超级块(super_block)、挂载描述符(mount结构体)、索引结点(inode结构体)、目录项(dentry结构体) 文件系统调用: 打开/关闭文件、 创建/删除文件、 读/写文件、 文件回写技术原理/接口实现 挂载文件系统:系统调用mount处理流程、绑定挂载/挂载命名空间、挂载/注册rootfs文件系统无 持久文件系统:proc文件系统(proc数据结构、装载proc/管理proc数据项、数据读取与写入实现)、 简单文件系统(顺序文件、调度文件系统、伪文件系统) 2:磁盘文件系统 Ext2文件系统:物理结构与数据结构、创建文件系统、操作文件系统 Ext3文件系统 Ext4文件系统 日志JBD2 3:用户空间文件系统 Fuse架构设计与原理 Fuse内核五大队列 Fuse用户空间流程与实现方案

  • 内核项目实战专题

    1-Linux内核编译与系统更换实现方法 2-进程间通信/管理(权限/优先级)实现方案 3-NIC网卡驱动实现 4-mmap系统调用/映射用户内存实现 5-Linux内存参数系统实现 6-调试与性能优化(debugfs/printk/ftrace) 7-Slab块分配器内存分配实现机制 8-tasklet/内线线程与定时器实现 9-Linux内核proc文件系统实现 10-Linux内核防火墙iptables实现

  • 适合于

  • Linux 内核优化、内存管理 ,内核开发岗位、定制化自己OS

  • 深入系统内核研究、网络安全逆向分析

  • 提升自己能力,为了更好做应用层开发提供核心依据

  • 跳槽面试大厂(腾讯、华为、中兴、中微、中芯等等)

  • 从事业务开发多年,对底层原理理解不够深入的在职工程师

  • 从事嵌入式方向开发,想转入内核开发的在职工程师

  • 从事Qt/MFC等桌面开发的,薪资多年涨幅不大的在职工程师

  • 从事非开发岗位(算法岗,运维岗,测试岗),想转内核开发岗位的在职工程师

  • 内核难点与学习方法:

  • 1、知识点多,关系错综复杂。

  • 2、每一个知识点的难度都很难。

  • 3、代码量很大,内核有几百万行。

  • 4、操作系统相关的知识。

  • 5、程序结构上的很多规范要求

  • 动手写代码

    纸上得来终觉浅,绝知此事要躬行。只看书是绝对不行的,一定要结合课本给出的编程建议自己敲代码。刚开始就以模块形式测试好了,或者自己编译一个开发版本的内核。一台机器的话,使用UML方式调试,内核控制路走到哪一步,单步调试看看程序执行过程,比书上的讲解更直观明了。一定要动手实际操作。

自学的弊端:网上资料繁杂,知识零碎,看过之后容易很快就忘掉,遇到问题只能自己钻研,有些很简单的问题不知不觉就浪费了很多时间,除非你是定力耐心毅力非常强的人,不然学习起来会没有方向感,盲目的看书枯燥乏味耗时比较长,会导致没有学习积极性失去信心与坚持下去的决心等等。总的来说自学不能说完全不行,只是适合少数人,自学的难度比报班系统学习一定是困难很多很多倍,多付出很多很多倍的。

反之报班学习的优势在于:

节约时间,知识串联:视频学习老师会提取知识点讲解出来比看书快了很多倍,并且理解起来比枯燥乏味的读书更有意思,尤其计算机相关的理论知识更是繁琐复杂交错依附,报班会让你更加系统的学习,知道前因后果来龙去脉,老师会把知识串联起来交给你,配套的资料发给你,而不是独立零散的知识点学习,对于提升来说,是高效且快速的。

老师答疑:遇到不懂得问题,老师会在自己看到的第一时间给到解答,24小时的答疑服务,会大大节约了你的学习时间。老师在知识体系,课程内容上,简历书写,面试指导,谈薪技巧等等方面都有着丰富的经验,课程内容也是由简到难,源码分析勾画重点,不做无用功,会提供配套的学习资料,图文并茂,讲解上通俗易懂,技术慢慢深入串联,学员通过和老师的沟通交流从而轻松学习,来达到自己想要达到的目标。

时间自由学习高效:很多在职的开发人员除了日常上班大部分时间还要加班,对于提升自己都是挤时间,没有完整的学习时间,这样其实给自学增添了很大的难度,跟着视频学习每日定好进度下班以后有固定的学习时间学习内容,或者周末抽几个小时整时间学习,有方向感且高效。

要说报班学习的弊端,那我只能想到一个,就是会有金钱上的一个付出,但是技术学会了是会跟随你一辈子的,现在的付出可能就是以后你一个月的涨薪部分,这个账怎么算都不会亏。投资自己 是风险最低 收益最高的,在大环境中安于现状才是井底之蛙,不断学习提升自己才是程序员最需要做的,提升工作竞争力,让自己在现在的公司被需要!

现如今各行各业内卷都很严重,不要说行业不行,而是大家越来越专业,这个是行业发展的必然性,优胜劣汰适者生存,时代在改变,不提高自己的核心竞争力就要出局。

最后:

给校招的小伙伴一句话:第一份工作不亚于一次高考,珍惜校招,社招的竞争是你目前想象不到的。能去大厂觉不妥协,IT行业第一份工作背景越好,起点越高,后续发展空间越好!

给那些1-3年的安于现状的伙伴一句话:

不要抱怨市场,不要安于现状,在低端,往中端领域看,在中端往高端领域看。认知以及对自身的要求,都会有所改变。

给那些担心35岁的伙伴一句话:

决定上限的不是年纪,而是技术。最后:希望学习路线对你有所帮助,希望码农的我们越来越好!

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多