牛客网论坛最具争议的 Linux 内核成神笔记,GitHub 已下载量已过百万
Linux 内核成神笔记:200+经典内核文章,100+内核论文,50+内核项目,500+内核面试题,80+内核视频
一,前言
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 日发布。
想知道什么是 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 内核的作用是什么?
内容有以下四项作用:
内存管理:追踪记录有多少内存存储了什么以及存储在哪里
进程管理:确定哪些进程可以使用中央处理器(CPU)、何时使用以及持续多长时间
设备驱动程序:充当硬件与进程之间的调解程序/解释程序
系统调用和安全防护:从流程接受服务请求
正确实现时,内核对用户是不可见的,它在自己的小世界(称为内核空间)中工作,从中分配内存,跟踪所有内容的存储位置。用户看到的东西(比如 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 来访问进程。
Linux 内核源代码的目录结构
Linux 内核源代码包括三个主要部分:
内核核心代码,包括第 3 章所描述的各个子系统和子模块,以及其它的支撑子系统,例如电源管理、Linux 初始化等
其它非核心代码,例如库文件(因为 Linux 内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等
编译脚本、配置文件、帮助文档、版权说明等辅助性文件使用 ls 命令看到的内核源代码的顶层目录结构,具体描述如下。include/ ---- 内核头文件,需要提供给外部模块(例如用户空间代码)使用。
二、为什么要学习 Linux 内核
大部分程序员可能永远没有机会开发 Linux 内核或者驱动 Linux,那么我们为什么还需要学习 Linux 内核呢?Linux 的源代码和架构都是开放的,我们可以学到很多操作系统的概念和实现原理。Linux 的设计哲学体系继承了 UNIX,现在整个设计体系相当稳定和简化,这是大部分服务器使用 Linux 的重要原因。
那学习 Linux 内核的原因就在于此。
进一步了解内核的原理,有助于你更好地使用命令和程序设计,让你的面试和开发更上一层楼。但是不建议直接看源代码,因为 Linux 代码太大,容易丢失。
而最好的办法是,先了解一下 Linux 内核机制,知道基本的原理与流程。
不过,Linux 内核机制也非常复杂,而且其中互相关联。
比如说,进程运行要分配内存,内存映射涉及文件的关联,文件的读写需要经过块设备,从文件中加载代码才能运行起来进程。这些知识点要反复对照,才能理清。
但是一旦攻克!你会发现 Linux 这个复杂的系统开始透明起来。
二、如何学习 Linux 内核?
内核的知识就像下面的绳结一样,一环扣一环,我们要解开它们,就必须要先找到线头也就是内核中的函数接口。初学阶段,我们一般不深入的研究内核代码,会使用内核的接口函数就不错了。
下面提供了如何学习这些内核函数的方法,就像解绳子一样
在我们学习 Linux 内核之前,我们首先需要掌握以下几点:
(4)最后依据我为大家提供的的学习资料,开启我们的Linux内核学习之旅。
(5)全网最牛Linux内核Makefile系统文件详解(纯文字代码)
(6)全网最详细的Intel CPU体系结构分析(内核源码)
(7)深入理解Linux Kernel内核整体架构(图文详解)
(9)网友说Linux驱动讲不彻底,原来这才是Linux驱动
(12)Linux用户空间与内核空间通信(Netlink通信机制)
二,学习资料
(1)系统调用接口【视频讲解】
SCI 层提供了某些机制执行从用户空间到内核的函数调用。正如前面讨论的一样,这个接口依赖于体系结构,甚至在相同的处理器家族内也是如此。SCI 实际上是一个非常有用的函数调用多路复用和多路分解服务。在 ./linux/kernel 中您可以找到 SCI 的实现,并在 ./linux/arch 中找到依赖于体系结构的部分。
(2)操作系统原理【视频讲解】
操作系统(英语:Operating System,缩写:OS)是一组主管并控制计算机操作、运用和运行硬件、软件资源和提供公共服务来组织用户交互的相互关联的系统软件程序。根据运行的环境,操作系统可以分为桌面操作系统,手机操作系统,服务器操作系统,嵌入式操作系统等。
【 强烈推荐阅读】一文带你彻底了解,零拷贝Zero-Copy技术(图解)
操作系统原理(三):Linux操作系统I/O机制原理(流程图详解)
系统操作原理(十一):操作系统原理:进程同步的几种方式及基本原理
系统操作原理(十二):趣谈操作系统原理,存储管理之页式、段式、段页式存储
系统操作原理(十三):操作系统:通过实战理解CPU上下文切换
(3)内存管理专题【视频讲解】
内核管理的另一个重要资源是内存。为了提高效率,如果虚拟内存由硬件管理,那么内存就按照所谓的内存分页法(大多数架构是 4KB)来管理。Linux 包括管理可用内存的方式和用于物理和虚拟映射的硬件机制。但是,内存管理需要管理 4KB 以上的缓冲区。Linux 提供了 4KB 缓冲区的抽象,比如 slab 分配器。这种内存管理模式以 4KB 缓冲区为基数,然后从中分配结构,并跟踪内存页面的使用情况,比如哪些页面已满,哪些页面未完全使用,哪些页面为空。这允许该模式根据系统需求动态调整内存使用。为了支持多个用户使用内存,有时会耗尽可用内存。因此,可以将页面移出内存,放入磁盘。这个过程称为交换,因为页面是从内存交换到硬盘的。内存管理的源代码可以在。/linux/mm。
【 强烈推荐阅读】尽情阅读,技术进阶,详解mmap原理
一文了解Linux内存管理,malloc、free 实现原理
内存管理系列(一):Linux操作系统内存管理(思维导图详解)
内存管理系列(三):学完操作系统内存管理,能回答这8个问题吗?
内存管理系列(四):理解 Memory barrier(内存屏障)
内存管理系列(七):Malloc缺页中断不同情况处理总结及反向映射RMAP
内存管理系列(八):C/C++开发中的Malloc函数的实现原理
内存管理系列(九):深入理解glibc malloc:内存分配器实现原理
内存管理系列(十):操作系统是如何对内存进行管理的,内存与CPU之间的关系
内存管理系列(十一):为什么Linux需要虚拟内存,虚拟内存对操作系统有哪些作用
内存管理系列(十四):C语言中的Malloc/free是如何分配内存的
内存管理系列(十五):从虚拟寻址到开源项目,Linux下的内存管理详解
内存管理系列(十六):一文带你了解,虚拟内存、内存分页、分段、段页式内存管理
内存管理系列(十八):虚拟地址到物理地址,是什么时候开始映射
内存管理系列(十九):浅析Linux内存管理中SLAB分配器(源码分析)
内存管理系列(二十):基于Linux内存管理的内存分配(伙伴算法和slab算法)
内存管理系列(二十一):探索内存原理的内存映射文件(图文详解)
内存管理系列(二十二):吊打字节面试官,CPU缓存一致性协议MESI
内存管理系列(二十三):深入理解Linux内核页表映射分页机制原理
内存管理系列(二十四):谈谈物理内存与虚拟内存之间的映射(超详细~)
内存管理系列(二十五):内存管理:C/C++开发中的malloc函数的实现原理
内存管理系列(二十六):熬夜肝翻Linux内存管理所有知识点(图解)
内存管理进阶部分(一):brk/kmalloc/vmalloc系统调用分析
内存管理进阶部分(三):页表缓存(TLB)与巨型页
内存管理进阶部分(四):TLB 表项格式及管理
内存管理进阶部分(五):ASID 原理/VMID 原理
内存管理进阶部分(七):标准巨型页原理及查看
内存管理进阶部分(八):LRU 算法与反向映射
内存管理进阶部分(九):缺页异常分析
内存管理进阶部分(十):写时复制缺页异常
内存管理进阶部分(十一):do_ page_ fault 函教分析
内存管理进阶部分(十三):匿名页面缺页异常
内存管理进阶部分(十四):内存反碎片技术
内存管理进阶部分(十五):内存碎片整理算法
内存管理进阶部分(十六):虚拟可移动区域技术原理
内存管理进阶部分(十七):内存检测与死锁检测
内存管理进阶部分(十八):内核调优参数
内存管理进阶部分(十九):/proc/sys/kernel/
内存管理进阶部分(二十三):编译器屏障
内存管理进阶部分(二十四):处理器屏障
内存管理进阶部分(二十五):ARM64 处理器内存屏障分析
内存管理进阶部分(二十七):五大常见内存访问错误
内存管理进阶部分(二十八):Kasan 内核检测工具应用
内存管理进阶部分(二十九):页回收原理机制
内存管理进阶部分(三十一):计算扫描页数
内存管理进阶部分(三十二):收缩活动页链表
内存管理进阶部分(三十三):回收不活动页
内存管理进阶部分(三十四):页交换与回收 slab 缓存
内存管理进阶部分(三十五):缓存着色
内存管理进阶部分(三十六):内存缓存数据结构
内存管理进阶部分(三十七):空闲对象链表及着色
内存管理进阶部分(三十八):内核调试方法 printk/oops 分析
内存管理实战操作(一): SIab 块分配器实现
内存管理实战操作(二):进程地址空间在内核(VMA 实现)
内存管理实战操作(六):perf 采集数据命令-29 种工具应用
内存管理实战操作(七):perf 采集数据至火焰图分析
(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进程六种状态吗?
进程管理系列(四):五分钟让你快速了解Linux进程管理实时调度与SMP
进程管理系列(七):进程管理|浅析C语言中并发同步与原子操作,锁三者是什么关系
进程管理系列(八):进程管理|深入理解Linux进程述符和进程状态
进程管理系列(九):一文读懂Linux内核中的任务间调度策略
进程管理系列(十三):一文搞懂六大进程通信机制原理(全网最详细)
进程管理系列(十四):超详细的Socket通信原理和实例讲解(白嫖走起~)
进程管理系列(十六):深入理解Linux内核进程的管理与调度(全知乎最详细)
x86_ _ARM处理器架构(五):SMP架构与NUMA架构
x86_ _ARM处理器架构(六):ARM Cortex-A9处理器架构
进程原理与生命周期及系统调用(六):实时调度类及SMP和NUMA
进程原理与生命周期及系统调用(七):task_ struct数据结构分析
进程原理与生命周期及系统调用(八):进程内核do_ fork()/kernel_ _clone()函数分析
进程原理与生命周期及系统调用(九):RCU机制及内存优化屏障
进程原理与生命周期及系统调用(十一):实战操作:内核数据结构(链表和红黑树)
(5)网络协议栈专题【视频讲解】
协议栈(英语:Protocol stack),又称协议堆叠,是计算机网络协议套件的一个具体的软件实现。协议套件中的一个协议通常是只为一个目的而设计的,这样可以使得设计更容易。因为每个协议模块通常都要和其他两个通信,它们通常可以想象成是协议栈中的层。最低级的协议总是描述与硬件的物理交互。每个高级的层次增加更多的特性。用户应用程序只是处理最上层的协议。使用最广泛的是英特网协议栈,由上到下的协议分别是:应用层(HTTP,TELNET,DNS,EMAIL 等),运输层(TCP,UDP),网络层(IP),链路层(WI-FI,以太网,令牌环,FDDI 等),物理层。
在实际中,协议栈通常分为三个主要部分:媒体,传输和应用。一个特定的操作系统或平台往往有两个定义良好的软件接口:一个在媒体层与传输层之间,另一个在传输层和应用程序之间。
媒体到传输接口定义了传输协议的软件怎样使用特定的媒体和硬件(“驱动程序”)。例如,此接口定义的 TCP/IP 传输软件怎么与以太网硬件对话。这些接口的例子包括 Windows 和 DOS 环境下的 ODI 和 NDIS。
应用到传输接口定义了应用程序如何利用传输层。例如,此接口定义一个网页浏览器程序怎样和 TCP/IP 传输软件对话。这些接口的例子包括 Unix 世界中的伯克利套接字和微软的 Winsock。
【 强烈推荐阅读】嵌入式必备:如何学习Linux内核网络协议栈
趣谈网络协议栈(五):Socket编程常用函数的原理及代码实现
趣谈网络协议栈(六):学习select和poll函数的内核实现
(6)设备驱动专题【视频讲解】
设备驱动程序是一种计算机程序,用于操作或控制连接到计算机的特定类型的设备。驱动程序提供了通往硬件设备的软件接口,从而使操作系统和其他计算机程序可以访问硬件功能,而无需知道有关所使用硬件的确切细节。
驱动程序通过硬件连接到的计算机总线或通信子系统与设备进行通信。当调用程序调用驱动程序中的例程时,驱动程序向设备发出命令。设备将数据发送回驱动程序后,驱动程序可以调用原始调用程序中的例程。驱动程序依赖于硬件且特定于操作系统。它们通常提供任何必要的异步时间相关的硬件接口所需的中断处理。
设备驱动基础架构(二):系统总线(PC1、ISA、SCSI、 USB 等)
设备驱动基础架构(三):与外设交互及控制设备
设备驱动基础架构(四):访问设备详解
设备驱动基础架构(六):块设备 1/0 操作集合及 源码分析
Linux 设备模型(一):深度剖析 LDM
Linux 设备模型(二):LDM 数据结构分析
Linux 设备模型(四):kobject 结构分析
Linux 设备模型(五):kobj_ _type/内核对象集合
Linux 设备模型(六):sysfs 文件及属性
Linux 设备模型(七):轮询 sysfs 属性文件
字符设备操作(一):主设备与次设备
字符设备操作(二):打开设备文件
字符设备操作(三):分配与注册字符设备
字符设备操作(四):写文件操作实现
字符设备操作(五):open/release 方法
字符设备操作(六):read/wr ite 方法
字符设备操作(七):Iseek/po11 方法
字符设备操作(八):填充 file_ operations 结构体
块设备操作(一):块设备表示与数据结构
块设备操作(二):向系统添加磁盘及分区
块设备操作(三):打开块设备文件
块设备操作(四):B10 数据结构
块设备操作(五):1/0 调度
块设备操作(六):ioctl 系统调用
块设备操作(七):总线系统模块
块设备操作(八):ISA 总线
块设备操作(九):PCI/PCI-E 总线
块设备操作(十):USB 总线
块设备操作(十一):通用驱动程序模型
浅谈设备驱动(三):结合设备信息集合,探究设备和驱动是如何绑定的
(7)文件系统【视频讲解】
虚拟文件系统(VFS)是 Linux 内核的一个非常有用的方面,因为它为文件系统提供了一个通用的接口抽象。VFS 在 SCI 和内核支持的文件系统之间提供了一个交换层(参见图 4)。
文件系统类型与文件模型研究(零):一文让你彻底了解Linux内核文件系统(大总结)
文件系统类型与文件模型研究(一):磁盘文件系统(DF)
文件系统类型与文件模型研究(三):i node
文件系统类型与文件模型研究(五):AP|编程接口
文件系统类型与文件模型研究(六):VFS 数据结构
文件系统类型与文件模型研究(七):超级块(super_ block)
文件系统类型与文件模型研究(八):挂载描述符 (mount 结构体)
文件系统类型与文件模型研究(九):索引结点(inode 结构体)
文件系统类型与文件模型研究(十):目录项缓存(dentry 结构体)
文件系统类型与文件模型研究(十一):文件系统调用打开/关闭文件
文件系统类型与文件模型研究(十二):文件系统调用创建/删除文件
文件系统类型与文件模型研究(十三):文件系统调用读/写文件实现
文件系统类型与文件模型研究(十四):文件回写技术原理/接口实现
文件系统类型与文件模型研究(十五):挂载文件系统系统调用mount处理流程
文件系统类型与文件模型研究(十六):挂载文件系统绑定挂载/挂载命名空间
文件系统类型与文件模型研究(十七):挂载文件系统挂载/注册 rootfs 文件系统
磁盘文件系统(一):Ext2 文件系统
磁盘文件系统(二):Ext2 物理结构
磁盘文件系统(三):Ext2 数据结构分析
磁盘文件系统(四):Ext2 文件系统操作
磁盘文件系统(五): Ext4_ 日志 JBD2
磁盘文件系统(六):Ext4 文件系统特性
磁盘文件系统(七):Ext4 文件系统数据结构
磁盘文件系统(八):Ext4_日志 JBD2
数据同步(一):内核定时器
数据同步(二):原子操作与屏障
数据同步(三):自旋锁机制
数据同步(四):自旋锁的实现与变体
数据同步(五):spin_ lock()/raw_ spin_ lock() 函数分析
数据同步(六):互斥锁
数据同步(一):mutex 数据结构分析
数据同步(一):互斥锁的快速与慢速通道
数据同步(一):乐观自旋锁等待机制
数据同步(一):mutex_ un lock()函数分析
数据同步(一):读写锁与 RCU
(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)面试题/经验
【 强烈推荐阅读】从事十年嵌入式转内核开发(23K到45K),给兄弟们的一些建议
盘点Linux内核(驱动开发,嵌入式,内核人群)必问的面试题
7、Linux 开机启动过程?8、Linux系统缺省的运行级别?
24、一台 Linux 系统初始化环境后需要做一些什么安全工作?
35、判断一文件是不是字符设备文件,如果是将其拷贝到 /dev 目录下?
36、添加一个新组为 class1 ,然后添加属于这个组的 30 个用户,用户名的形式为 stdxx ,其中 xx 从 01 到 30 ?
37、写一个 sed 命令,修改 /tmp/input.txt 文件的内容?
40、Linux 虚拟文件系统的关键数据结构有哪些?(至少写出四个)
45、Linux 调度程序是根据进程的动态优先级还是静态优先级来调度进程的?
65、添加一条到192.168.3.0/24的路由,网关为192.168.1.254?
67、如何在/home目录下找出120天之前被修改过的文件?
68、在整个目录树下查找文件“core”,如发现则无需提示直接删除它们。
69、有一普通用户想在每周日凌晨零点零分定期备份/user/backup到/tmp目录下,该用户应如何做?70、每周一下午三点将/tmp/logs目录下面的后缀为*.log的所有文件rsync同步到备份服务器192.168.1.100中同样的目录下面,crontab配置项该如何写?
71、找到/tmp/目录下面的所有名称以"s1.jpg"结尾的普通文件,如果其修改日期在一天内,则将其打包到/tmp/back.tar.gz文件中
72、配置mysql服务器的时候,配置了auto_increment_increment=3,请问这里的3意味着什么?73、详细说明keepalived的故障切换工作原理
1、绝对路径用什么符号表示?当前目录、上层目录用什么表示?主目录用什么表示? 切换目录用什么命令?
3、怎么清屏?怎么退出当前命令?怎么执行睡眠?怎么查看当前用户 id?查看指定帮助用什么命令?4、Ls 命令执行什么功能? 可以带哪些参数,有什么区别?
6、目录创建用什么命令?创建文件用什么命令?复制文件用什么命令?
9、随意写文件命令?怎么向屏幕输出带空格的字符串,比如”hello world”?
10、终端是哪个文件夹下的哪个文件?黑洞文件是哪个文件夹下的哪个命令?
12、复制文件用哪个命令?如果需要连同文件夹一块复制呢?如果需要有提示功能呢?
13、删除文件用哪个命令?如果需要连目录及目录下文件一块删除呢?删除空文件夹用什么命令?14、Linux 下命令有哪几种可使用的通配符?分别代表什么含义?
15、用什么命令对一个文件的内容进行统计?(行号、单词数、字节数)
16、Grep 命令有什么用? 如何忽略大小写? 如何查找不含该串的行?
17、Linux 中进程有哪几种状态?在 ps 显示出来的信息中,分别用什么符号表示的?
19、利用 ps 怎么显示所有的进程? 怎么利用 ps 查看指定进程的信息?
21、把后台任务调到前台执行使用什么命令?把停下的后台任务在后台执行起来用什么命令?
25、查看当前谁在使用该主机用什么命令? 查找自己所在的终端信息用什么命令?
32、查找命令的可执行文件是去哪查找的? 怎么对其进行设置及添加?
37、当你需要给命令绑定一个宏或者按键的时候,应该怎么做呢?
38、如果一个linux新手想要知道当前系统支持的所有命令的列表,他需要怎么做?
39、如果你的助手想要打印出当前的目录栈,你会建议他怎么做?
40、你的系统目前有许多正在运行的任务,在不重启机器的条件下,有什么方法可以把所有正在运行的进程移除呢?
45、怎样查看一个linux命令的概要与用法?假设你在/bin目录中偶然看到一个你从没见过的的命令,怎样才能知道它的作用和用法呢?
(13)内核书籍
《深入了解 Linux 内核》
《Linux 就该这么学》
《Linux 内核完全注释 V3.0 书签版》
《Linux 命令行大全 - 绍茨 (william E.shotts)》
《Linux 命令速查手册》
《Linux 性能优化大师》
《Linux 环境编程:从应用到内核》
《Linux 集群和自动化运维 余洪春》
《Linux 驱动程序开发实例(第 2 版)》
《Linux 高级程序设计(第 3 版)》
《构建高可用 Linux 服务器(第 4 版)》
书籍免费领取地址:https://docs.qq.com/doc/DTkZRWXRFcWx1bWVx
三、怎么阅读源码
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 内核体系
4.1Linux 内核体系结构简析简析
顶部是用户(或应用程序)空间。这是用户应用程序执行的地方。用户空间下面是内核空间,Linux 内核就位于这里。GNU C 库(glibc)也在这里。它为内核提供了一个系统调用接口,也为用户空间应用程序和内核之间的转换提供了一个机制。这非常重要,因为内核和用户空间应用程序使用不同的受保护地址空间。每个用户空间进程使用自己的虚拟地址空间,而内核占用一个单独的地址空间。
Linux 内核可以进一步分为 3 层。最上面是系统调用接口,实现一些基本功能,比如读写。系统调用接口下面是内核代码,可以更准确的定义为独立于架构的内核代码。这些代码对于 Linux 支持的所有处理器架构都是通用的。在这些代码下面是依赖于架构的代码,它构成了通常称为 BSP(板支持包)的部分。这些代码用作给定架构的处理器和平台特定代码。
Linux 内核实现了许多重要的架构属性。在更高或更低的层次上,内核被分成几个子系统。Linux 也可以看做一个整体,因为它会把这些基础服务都集成到内核中。这与微内核的架构不同,微内核提供一些基本的服务,比如通信、I/O、内存、进程管理等。更具体的服务被插入到微内核层中。每个内核都有自己的优点,但这里不讨论这个。
随着时间的推移,Linux 内核在内存和 CPU 使用上的效率很高,非常稳定。但对于 Linux 来说,最有意思的是,在这个规模和复杂度的前提下,它仍然具有良好的可移植性。经过编译后,Linux 可以在大量具有不同架构约束和要求的处理器和平台上运行。例如,Linux 可以运行在带有内存管理单元(MMU)的处理器上,也可以运行在不提供 MMU 的处理器上。linux 内核的 UClinux 移植提供了对非 MMU 的支持。
Linux 内核的主要组件有:系统调用接口、进程管理、内存管理、虚拟文件系统、网络堆栈、设备驱动程序、硬件架构的相关代码。
4.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. 开源社区:需要了解开源社区的文化和开发流程,以便更好地参与内核开发。
总之,转向内核开发需要广泛的知识储备和实践经验,需要不断学习和探索。
个人建议参加零声教育的培训,学习效率会高很多,有目的性的参加培训,缩短周期,快速成型才是时代所需。Linux内核源码学习。
内核学习路线推荐,喜欢研究内核,想在内核这块深入学习的,可以参考。
操作系统原理/汇编专题
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 内核视频讲解
1、深度剖析 Linux 内核 SMP 负载均衡-----视频讲解地址
2、深度剖析 Linux 内核 ARM64 处理器架构-----视频讲解地址
3、深度剖析 Linux 内核 ARM 异常处理-----视频讲解地址
4、深度剖析 Linux 内核 CFS 调度器-----视频讲解地址
5、深度剖析 Linux 内核量化负载计算能力-----视频讲解地址
6、深度剖析 Linux 内核进程及生命周期-----视频讲解地址
7、深度剖析 Linux 内核 CPU 域初始化实现-----视频讲解地址
8、深度剖析 Linux 内核蓝牙子系统架构-----视频讲解地址
9、深度剖析 Linux 内核 USB 系统架构-----视频讲解地址
10、深度剖析 Linux 内核 IO 体系结构与访问设备-----视频讲解地址
11、深度剖析 Linux 内核进程管理机制-----视频讲解地址
12、深度剖析 Linux 内核 MLFQ 经典调度算法-----视频讲解地址
13、深入剖析 Linux 内核伙伴系统实现及 API 调度实战-----视频讲解地址
14、深入剖析 Linux 内核哈希表与运行队列-----视频讲解地址
15、深入剖析 Linux 内核 NUMA 调度器-----视频讲解地址
16、深度剖析 Linux 内核 perf 性能优化分析-----视频讲解地址
七、内核项目实战
以上就是 Linux 内核学习路线,关于学习 Linux 内核的建议,希望对小伙伴们有帮
版权声明: 本文为 InfoQ 作者【简说Linux内核】的原创文章。
原文链接:【http://xie.infoq.cn/article/95df0eedce224b7cce193987d】。文章转载请联系作者。
评论