Linux内核源码分析(强烈推荐收藏!)

发布时间:2024年01月11日

前言:Linux内核是由林纳斯·托瓦兹(Linus Torvalds)在1991年开始开发的。当时他为了得到一个可以运行UNIX操作系统的个人计算机,开始编写一个操作系统内核,并将其命名为Linux。随后,越来越多的开发者加入到项目中,共同完善和扩展Linux内核。如今,Linux已经成为最流行和广泛使用的开源操作系统内核之一,驱动着许多不同类型的设备和服务器。

一,Linux内核简述

Linux内核是一个操作系统(OS)内核,本质上定义为类Unix。它用于不同的操作系统,主要是以不同的Linux发行版的形式。Linux内核是第一个真正完整且突出的免费和开源软件示例。Linux 内核是第一个真正完整且突出的免费和开源软件示例,促使其广泛采用并得到了数千名开发人员的贡献。

Linux 内核由芬兰赫尔辛基大学的学生 Linus Torvalds 于 1991 年创建。随着程序员调整其他自由软件项目的源代码以扩展内核的功能,它迅速取得了进展。Torvalds 首先使用 80386 汇编语言编写的任务切换器以及终端驱动程序,然后将其发布到 Comp.os.minix Usenet 组。它很快被 Mini社区所改编,为该项目提供了见解和代码。

Linux 内核越来越受欢迎,因为 GNU 自己的内核 GNU Hurd 不可用且不完整,而 Berkeley Software DistribuTIon(BSD)操作系统仍然受到法律问题的困扰。在开发人员社区的帮助下,Linux 0.01 于 1991 年 9 月 17 日发布。

精品文章推荐:

C/C++发展方向(强烈推荐!!)

深入探索Linux内核:了解内核源代码结构与组织

Linux C/C++开发上线项目(后端、音视频、存储、QT)

2023年C/C++高性能技术知识大整理(进阶到大神级别)

2023年音视频开发知识技术合集(基础入门到高级进阶)

想知道什么是 Linux 内核上真正的(不是那种时髦的)创新吗?

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux 内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大物。

撇开营销和模式不谈,Linux 可以说是开源世界中最受欢迎的内核,它在近 30 年的生命时光当中引入了一些真正的规则改变者。

Cgroups(2.6.24)

早在 2007 年,Paul Menage 和 Rohit Seth 就在内核中添加了深奥的控制组(cgroups)功能(cgroups 的当前实现是由 Tejun Heo 重写的)。这种新技术最初被用作一种方法,从本质上来说,是为了确保一组特定任务的服务质量。

例如,你可以为与你的 WEB 服务相关联的所有任务创建一个控制组定义(cgroup),为例行备份创建另一个 cgroup ,再为一般操作系统需求创建另一个 cgroup。然后,你可以控制每个组的资源百分比,这样你的操作系统和 WEB 服务就可以获得大部分系统资源,而你的备份进程可以访问剩余的资源。

然而,cgroups 如今变得这么著名是因其作为驱动云技术的角色:容器。事实上,cgroups 最初被命名为进程容器。当它们被 LXC、CoreOS 和 Docker 等项目采用时,这并不奇怪。

就像闸门打开后一样,“容器” 一词就像成为了 Linux 的同义词一样,微服务风格的基于云的“应用”概念很快成为了规范。如今,已经很难摆脱 cgroups 了,它们是如此普遍。每一个大规模的基础设施(如果你运行 Linux 的话,可能还有你的笔记本电脑)都以一种合理的方式使用了 cgroups,这使得你的计算体验比以往任何时候都更加易于管理和灵活。

例如,你可能已经在电脑上安装了 Flathub 或 Flatpak,或者你已经在工作中使用 Kubernetes 和/或 OpenShift。不管怎样,如果“容器”这个术语对你来说仍然模糊不清,则可以 通过 Linux 容器从背后获得对容器的实际理解。

LKMM(4.17)

2018 年,Jade Alglave、Alan Stern、Andrea Parri、Luc Maranget、Paul McKenney 以及其他几个人的辛勤工作的成果被合并到主线 Linux 内核中,以提供正式的内存模型。Linux 内核内存[一致性]模型(LKMM)子系统是一套描述 Linux 内存一致性模型的工具,同时也产生用于测试的用例(特别命名为 klitmus)。

随着系统在物理设计上变得越来越复杂(增加了更多的中央处理器内核,高速缓存和内存增长,等等),它们就越难知道哪个中央处理器需要哪个地址空间,以及何时需要。例如,如果 CPU0 需要将数据写入内存中的共享变量,并且 CPU1 需要读取该值,那么 CPU0 必须在 CPU1 尝试读取之前写入。类似地,如果值是以一种顺序方式写入内存的,那么期望它们也以同样的顺序被读取,而不管哪个或哪些 CPU 正在读取。

即使在单个处理器上,内存管理也需要特定的任务顺序。像 x = y 这样的简单操作需要处理器从内存中加载 y 的值,然后将该值存储在 x 中。在处理器从内存中读取值之前,是不能将存储在 y 中的值放入 x 变量的。此外还有地址依赖:x[n] = 6 要求在处理器能够存储值 6 之前加载 n。

LKMM 可以帮助识别和跟踪代码中的这些内存模式。它部分是通过一个名为 herd 的工具来实现的,该工具(以逻辑公式的形式)定义了内存模型施加的约束,然后列举了与这些约束一致性的所有可能的结果。

低延迟补丁(2.6.38)

很久以前,在 2011 年之前,如果你想在 Linux 上进行多媒体工作,你必须得有一个低延迟内核。这主要适用于录音时添加了许多实时效果(如对着麦克风唱歌和添加混音,以及在耳机中无延迟地听到你的声音)。有些发行版,如 Ubuntu Studio,可靠地提供了这样一个内核,所以实际上这没有什么障碍,这只不过是当艺术家选择发行版时的一个重要提醒。

然而,如果你没有使用 Ubuntu Studio,或者你需要在你的发行版提供之前更新你的内核,你必须跳转到 rt-patches 网页,下载内核补丁,将它们应用到你的内核源代码,编译,然后手动安装。

后来,随着内核版本 2.6.38 的发布,这个过程结束了。Linux 内核突然像变魔术一样默认内置了低延迟代码(根据基准测试,延迟至少降低了 10 倍)。不再需要下载补丁,不用编译。一切都很顺利,这都是因为 Mike Galbraith 编写了一个 200 行的小补丁。

对于全世界的开源多媒体艺术家来说,这是一个规则改变者。从 2011 年开始事情变得如此美好,到 2016 年我自己做了一个挑战,在树莓派 v1(型号 B)上建造一个数字音频工作站(DAW),结果发现它运行得出奇地好。

RCU(2.5)

RCU,即 读-拷贝-更新(Read-Copy-Update),是计算机科学中定义的一个系统,它允许多个处理器线程从共享内存中读取数据。它通过延迟更新但也将它们标记为已更新来做到这一点,以确保数据读取为最新内容。实际上,这意味着读取与更新同时发生。

典型的 RCU 循环有点像这样:

  • 删除指向数据的指针,以防止其他读操作引用它。
  • 等待读操作完成它们的关键处理。
  • 回收内存空间。

将更新阶段划分为删除和回收阶段意味着更新程序会立即执行删除,同时推迟回收直到所有活动读取完成(通过阻止它们或注册一个回调以便在完成时调用)。

虽然 RCU 的概念不是为 Linux 内核发明的,但它在 Linux 中的实现是该技术的一个定义性的例子。

对于 Linux 内核创新的问题的最终答案永远是协作。你可以说这是一个好时机,也可以称之为技术优势,称之为黑客能力,或者仅仅称之为开源,但 Linux 内核及其支持的许多项目是协作与合作的光辉范例。

它远远超出了内核范畴。各行各业的人都对开源做出了贡献,可以说都是因为 Linux 内核。Linux 曾经是,现在仍然是自由软件的主要力量,激励人们把他们的代码、艺术、想法或者仅仅是他们自己带到一个全球化的、有生产力的、多样化的人类社区中。

你最喜欢的创新是什么?

这个列表偏向于我自己的兴趣:容器、非统一内存访问(NUMA)和多媒体。无疑,列表中肯定缺少你最喜欢的内核创新。在评论中告诉我。

1.1内核在操作系统中的位置

为了更具象地理解内核,不妨将Linux计算机想象成有三层结构:

硬件:物理机(这是系统的底层结构或基础)是由内存(RAM)、处理器(或 CPU)以及输入/输出(I/O)设备(例如存储、网络和图形)组成的。其中,CPU 负责执行计算和内存的读写操作。

Linux 内核:操作系统的核心。(没错,内核正处于核心的位置)它是驻留在内存中的软件,用于告诉 CPU 要执行哪些操作。

用户进程:这些是内核所管理的运行程序。用户进程共同构成了用户空间。用户进程有时也简称为进程。内核还允许这些进程和服务器彼此进行通信(称为进程间通信或 IPC)。

系统执行的代码在CPU上以以下两种模式之一运行:内核模式或用户模式。运行在内核态的代码可以不受限制地访问硬件,而用户态会限制SCI对CPU和内存的访问。内存也有类似的分离(内核空间和用户空间)。这两个小细节构成了一些复杂操作的基础,比如安全保护,构建容器和虚拟机的权限分离。

这也意味着,如果进程在用户模式下失败,损失是有限且无害的,并且可以由内核修复。另一方面,由于内核进程要访问内存和处理器,内核进程的崩溃可能会导致整个系统的崩溃。因为用户进程之间会有适当的保护措施和权限要求,所以一个进程的崩溃通常不会造成太多问题。

此外,由于Linux内核在实时补丁期间可以连续工作,因此在应用补丁进行安全修复时不会出现宕机。

1.2Linux 内核的作用是什么?

内容有以下四项作用:

  1. 内存管理:追踪记录有多少内存存储了什么以及存储在哪里
  2. 进程管理:确定哪些进程可以使用中央处理器(CPU)、何时使用以及持续多长时间
  3. 设备驱动程序:充当硬件与进程之间的调解程序/解释程序
  4. 系统调用和安全防护:从流程接受服务请求

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

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

1.3学习Linux内核准备工作:

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

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

学过或者自学过计算机组成原理或者微机原理,知道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来访问进程。

1.4Linux内核源代码的目录结构

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

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

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

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

在这里插入图片描述

kernel/ ---- Linux内核的核心代码,包含了3.2小节所描述的进程调度子系统,以及和进程调度相关的模块。
mm/ ---- 内存管理子系统(3.3小节)。
fs/ ---- VFS子系统(3.4小节)。
net/ ---- 不包括网络设备驱动的网络子系统(3.5小节)。
ipc/ ---- IPC(进程间通信)子系统。
arch// ---- 体系结构相关的代码,例如arm, x86等等。
arch//mach- ---- 具体的machine/board相关的代码。
arch//include/asm ---- 体系结构相关的头文件。
arch//boot/dts ---- 设备树(Device Tree)文件。
init/ ---- Linux系统启动初始化相关的代码。
block/ ---- 提供块设备的层次。
sound/ ---- 音频相关的驱动及子系统,可以看作“音频子系统”。
drivers/ ---- 设备驱动(在Linux kernel 3.10中,设备驱动占了49.4的代码量)。
lib/ ---- 实现需要在内核中使用的库函数,例如CRC、FIFO、list、MD5等。
crypto/ ----- 加密、解密相关的库函数。
security/ ---- 提供安全特性(SELinux)。
virt/ ---- 提供虚拟机技术(KVM等)的支持。
usr/ ---- 用于生成initramfs的代码。
firmware/ ---- 保存用于驱动第三方设备的固件。
samples/ ---- 一些示例代码。
tools/ ---- 一些常用工具,如性能剖析、自测试等。
Kconfig, Kbuild, Makefile, scripts/ ---- 用于内核编译的配置文件、脚本等。
COPYING ---- 版权声明。
MAINTAINERS ----维护者名单。
CREDITS ---- Linux主要的贡献者名单。
REPORTING-BUGS ---- Bug上报的指南。
Documentation, README ---- 帮助、说明文档。

二、为什么要学习 Linux 内核

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

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

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

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

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

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

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

三、如何学习Linux内核?

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

下面提供了如何学习这些内核函数的方法,就像解绳子一样

(1)系统调用接口

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

(2)操作系统原理

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

(3)内存管理专题

内核管理的另一个重要资源是内存。为了提高效率,如果虚拟内存由硬件管理,那么内存就按照所谓的内存分页法(大多数架构是4KB)来管理。Linux包括管理可用内存的方式和用于物理和虚拟映射的硬件机制。但是,内存管理需要管理4KB以上的缓冲区。Linux提供了4KB缓冲区的抽象,比如slab分配器。这种内存管理模式以4KB缓冲区为基数,然后从中分配结构,并跟踪内存页面的使用情况,比如哪些页面已满,哪些页面未完全使用,哪些页面为空。这允许该模式根据系统需求动态调整内存使用。为了支持多个用户使用内存,有时会耗尽可用内存。因此,可以将页面移出内存,放入磁盘。这个过程称为交换,因为页面是从内存交换到硬盘的。内存管理的源代码可以在/linux/mm。

(4)进程管理专题

进程管理的重点是流程的实施。在内核中,这些进程称为线程,代表单个处理器虚拟化(线程代码、数据、堆栈和CPU寄存器)。在用户空间中,通常使用术语进程,但是Linux实现没有区分这两个概念(进程和线程)。内核SCI提供了一个应用程序编程接口(API)来创建一个新的进程(fork,exec或可移植操作系统接口[POSIX]函数),停止进程(kill,exit),并进行通信和同步(signal或POSIX机制)。

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

(5)网络协议栈专题

协议栈(英语:Protocol stack),又称协议堆叠,是计算机网络协议套件的一个具体的软件实现。协议套件中的一个协议通常是只为一个目的而设计的,这样可以使得设计更容易。因为每个协议模块通常都要和其他两个通信,它们通常可以想象成是协议栈中的层。最低级的协议总是描述与硬件的物理交互。每个高级的层次增加更多的特性。用户应用程序只是处理最上层的协议。使用最广泛的是英特网协议栈,由上到下的协议分别是:应用层(HTTP,TELNET,DNS,EMAIL等),运输层(TCP,UDP),网络层(IP),链路层(WI-FI,以太网,令牌环,FDDI等),物理层。

在实际中,协议栈通常分为三个主要部分:媒体,传输和应用。一个特定的操作系统或平台往往有两个定义良好的软件接口:一个在媒体层与传输层之间,另一个在传输层和应用程序之间。

媒体到传输接口定义了传输协议的软件怎样使用特定的媒体和硬件(“驱动程序”)。例如,此接口定义的TCP/IP传输软件怎么与以太网硬件对话。这些接口的例子包括Windows和DOS环境下的ODI和NDIS。

应用到传输接口定义了应用程序如何利用传输层。例如,此接口定义一个网页浏览器程序怎样和TCP/IP传输软件对话。这些接口的例子包括Unix世界中的伯克利套接字和微软的Winsock。

(6)设备驱动专题

设备驱动程序是一种计算机程序,用于操作或控制连接到计算机的特定类型的设备。驱动程序提供了通往硬件设备的软件接口,从而使操作系统和其他计算机程序可以访问硬件功能,而无需知道有关所使用硬件的确切细节。

驱动程序通过硬件连接到的计算机总线或通信子系统与设备进行通信。当调用程序调用驱动程序中的例程时,驱动程序向设备发出命令。设备将数据发送回驱动程序后,驱动程序可以调用原始调用程序中的例程。驱动程序依赖于硬件且特定于操作系统。它们通常提供任何必要的异步时间相关的硬件接口所需的中断处理。

(7)文件系统

虚拟文件系统(VFS)是Linux内核的一个非常有用的方面,因为它为文件系统提供了一个通用的接口抽象。VFS在SCI和内核支持的文件系统之间提供了一个交换层。

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

(9)设备驱动程序

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

(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也可以虚拟化。唯一的限制是底层处理器必须支持新的虚拟化指令。

(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也可以虚拟化。唯一的限制是底层处理器必须支持新的虚拟化指令。

(12)面试题/经验

(13)内核书籍

  • 《深入了解Linux内核》
  • 《Linux就该这么学》
  • 《Linux内核完全注释V3.0书签版》
  • 《Linux命令行大全 - 绍茨 (william E.shotts)》
  • 《Linux命令速查手册》
  • 《Linux性能优化大师》
  • 《Linux环境编程:从应用到内核》
  • 《Linux集群和自动化运维 余洪春》
  • 《Linux驱动程序开发实例(第2版)》
  • 《Linux高级程序设计(第3版)》
  • 《构建高可用Linux服务器(第4版)》

四、怎么阅读源码

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

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

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

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

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

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

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

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

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

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

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

查看代码的工具

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

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

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

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

五、Linux内核体系

5.1Linux内核体系结构简析简析

在这里插入图片描述
顶部是用户(或应用程序)空间。这是用户应用程序执行的地方。用户空间下面是内核空间,Linux内核就位于这里。GNU C库(glibc)也在这里。它为内核提供了一个系统调用接口,也为用户空间应用程序和内核之间的转换提供了一个机制。这非常重要,因为内核和用户空间应用程序使用不同的受保护地址空间。每个用户空间进程使用自己的虚拟地址空间,而内核占用一个单独的地址空间。

Linux内核可以进一步分为3层。最上面是系统调用接口,实现一些基本功能,比如读写。系统调用接口下面是内核代码,可以更准确的定义为独立于架构的内核代码。这些代码对于Linux支持的所有处理器架构都是通用的。在这些代码下面是依赖于架构的代码,它构成了通常称为BSP(板支持包)的部分。这些代码用作给定架构的处理器和平台特定代码。

Linux内核实现了许多重要的架构属性。在更高或更低的层次上,内核被分成几个子系统。Linux也可以看做一个整体,因为它会把这些基础服务都集成到内核中。这与微内核的架构不同,微内核提供一些基本的服务,比如通信、I/O、内存、进程管理等。更具体的服务被插入到微内核层中。每个内核都有自己的优点,但这里不讨论这个。

随着时间的推移,Linux内核在内存和CPU使用上的效率很高,非常稳定。但对于Linux来说,最有意思的是,在这个规模和复杂度的前提下,它仍然具有良好的可移植性。经过编译后,Linux可以在大量具有不同架构约束和要求的处理器和平台上运行。例如,Linux可以运行在带有内存管理单元(MMU)的处理器上,也可以运行在不提供MMU的处理器上。linux内核的UClinux移植提供了对非MMU的支持。
在这里插入图片描述
Linux内核的主要组件有:系统调用接口、进程管理、内存管理、虚拟文件系统、网络堆栈、设备驱动程序、硬件架构的相关代码。

5.2内核模块

如果Windows已经安装了所有可用的驱动程序,而您只需要打开所需的驱动程序怎么办?这本质上就是内核模块为Linux所做的。内核模块,也称为可加载内核模块(LKM),对于保持内核在不消耗所有可用内存的情况下与所有硬件一起工作是必不可少的。
在这里插入图片描述

模块通常向基本内核添加诸如设备、文件系统和系统调用等功能。lkm的文件扩展名是。ko,它通常存储在/lib/modules目录中。由于模块的特性,您可以通过在启动时使用menuconfig命令将模块设置为加载或不加载,或者通过编辑/boot/config文件,或者使用modprobe命令动态加载和卸载模块,来轻松定制内核。第三方和封闭源代码模块在某些发行版中可用,如Ubuntu,默认情况下可能不会安装,因为这些模块的源代码不可用。该软件的开发商(即nVidia、ATI等。)不提供源代码,而是自己搭建模块,编译所需。用于分发的ko文件。虽然这些模块像啤酒一样是免费的,但它们不像语音一样是免费的,所以它们没有包含在一些发行版中,因为维护者认为它通过提供非自由软件来“污染”内核。内核并不神奇,但对于任何一台正常的电脑都是必不可少的。Linux内核不同于OS X和Windows,因为它包含内核级驱动程序,并使许多东西“开箱即用”。我希望你能更多地了解软件和硬件是如何配合工作的,以及启动电脑所需的文件。

六、学习Linux内核

学习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仅是指操作系统的内核,作为科班出生的你不要让我解释,我也没时间。

我推荐的发行版如下:

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

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

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

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也是必修课。这是开发的第一步,注意我并没有提过一句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程序设计艺术,世界顶级黑客将同你分享他的看法。现在是时候做分流了。大体上我分为四个方向:网络,图形,嵌入式,设备驱动。

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

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

  • APUE再深读 – 尤其是进程,线程,IPC,套接字
  • 多核程序设计 - Pthread一定得吃透了,你很NB
  • UNIX网络编程 – 卷一,卷二
  • TCP/IP网络详解 – 卷一 再看上面两本书时就该看了
  • TCP/IP 网络详解 – 卷二 我觉得看到卷二就差不多了,当然卷三看了更好,努力,争取看了
  • Lighttpd源代码 - 这个服务器也很有名了
  • Nginx源代码 – 相较于Apache,Nginx的源码较少,如果能看个大致,很NB。看源代码主要是要学习里面的套接字编程及并发控制,想想都激动。如果你有这些本事,可以试着往暴雪投简历,为他们写服务器后台,想一想全球的魔兽都运行在你的服务器软件上。
  • 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. 开源社区:需要了解开源社区的文化和开发流程,以便更好地参与内核开发。

本文福利, 免费领取C/C++ 开发学习资料包、技术视频/代码,1000道大厂面试题,内容包括
(C++基础,网络编程,数据库,中间件,后端开发/音视频开发/Qt开发/游戏开发/Linuxn内核等进阶学习资料和学习路线)
↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

文章来源:https://blog.csdn.net/m0_50662680/article/details/135478253
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。