ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux内核学习路线图:从运维到嵌入式开发的总目录指南

Linux内核学习路线图:从运维到嵌入式开发的总目录指南 1. 这个专栏到底想解决什么问题做Linux内核学习内容这几年我被问得最多的一句话就是“内核源码一百多万行我到底该从哪儿看起”这个问题背后其实藏着三层焦虑第一层是不知道学什么第二层是不知道按什么顺序学第三层是学完了不知道能干什么。市面上讲内核的资料不少但要么是散落在各个博客里的单点知识要么是厚得像砖头的教材中间缺了一条能把零散知识串起来的线。这个专栏要做的就是这条线。它不是一本电子书也不是一套视频课程而是一个持续更新的总目录把Linux内核相关的核心知识点按照“从使用到理解、从外围到核心、从理论到落地”的逻辑重新编排。你可以把它理解成一张地图图上标注了每个知识点的位置、难度、前置依赖和实际用途你照着走就不会迷路。适合谁来参考三类人。第一类是运维工程师平时用Linux命令很熟但遇到内核参数调优、性能瓶颈定位就发怵想补上底层这块短板。第二类是嵌入式开发方向的从业者需要做内核裁剪、驱动移植但一直停留在改配置文件的层面想搞清楚背后的机制。第三类是计算机专业的学生或者转行的人操作系统课学过进程调度、内存管理这些概念但没真正看过内核代码想找一个能落地的学习路径。这个总目录的价值在于它把“学内核”这件事从“啃源码”变成了“按需取用”。你不需要从头到尾读完所有内容而是可以根据自己当前的工作场景找到对应的章节直接切入。比如你正在排查一个内存泄漏问题那就直接跳到内存管理部分你在做启动优化那就先看启动流程和裁剪相关的章节。这种按需学习的方式比线性阅读效率高得多。2. 专栏的整体架构与学习路径设计2.1 为什么采用“总目录分篇”的结构一开始我也想过按传统教材的方式从进程管理讲到内存管理再讲到文件系统一章一章往下写。但实际写了几篇之后发现一个问题读者反馈说“看的时候都懂关掉页面就忘”。原因很简单内核知识是网状结构不是线性的。进程调度会牵扯到内存分配内存分配又会牵扯到文件系统的页缓存你硬要拆成独立的章节反而割裂了它们之间的联系。所以这个专栏改成了“总目录分篇”的结构。总目录负责建立全局认知告诉你每个知识点在整个体系中的位置以及它和其他知识点的关联。分篇则深入具体的技术细节每篇都可以独立阅读但读完之后你会知道它在总目录中的坐标。这种结构的好处是你既可以按顺序系统学习也可以跳着看解决眼前的问题两种方式都不影响理解。另一个考虑是更新节奏。内核版本迭代很快从4.x到5.x再到6.x很多机制都在变化。如果按传统教材的方式写写完可能就过时了。总目录的形式允许我持续更新某个知识点有了新变化我只需要更新对应的分篇总目录里调整一下链接和说明就行。读者也不用担心看到过时的内容因为每个分篇都会标注适用的内核版本范围。2.2 学习路径的三种走法根据我自己的学习经验和读者的反馈这个专栏设计了三条学习路径你可以根据自己的背景和目标选择。第一条是“运维实战路径”适合已经会基本Linux操作、想深入理解系统行为的运维人员。这条路径从常用命令的底层原理切入先讲清楚你每天敲的top、free、iostat这些命令背后读的是哪些内核数据然后延伸到性能调优、故障排查、参数配置。走完这条路径你看到系统卡顿的时候脑子里会有一个清晰的排查链条而不是盲目地重启服务。第二条是“嵌入式开发路径”适合做驱动开发、内核裁剪的工程师。这条路径从内核源码结构讲起然后是配置系统、编译流程、启动过程再深入到设备树、驱动模型、中断处理。重点在于让你理解“为什么这样配置”而不是“照着文档改就行”。比如内核裁剪很多人只会用make menuconfig勾勾选选但不知道每个选项背后的依赖关系结果裁出来的内核要么启动不了要么功能缺失。这条路径会把这些依赖关系讲清楚。第三条是“面试与原理路径”适合准备面试或者想系统补基础的人。这条路径按照操作系统的经典模块来组织进程管理、内存管理、文件系统、网络协议栈、同步与并发。每个模块先讲核心概念和数据结构再讲关键流程和算法最后讲常见的面试问题和实际案例。走完这条路径你不仅能回答“进程和线程的区别”这种基础问题还能深入到底层实现层面。三条路径不是互斥的你可以先走一条再补充另外两条。总目录里会用不同的标记来区分每条路径包含的章节方便你筛选。2.3 内容编排的取舍逻辑在编排内容的时候我做了几个关键的取舍这里说明一下背后的考虑。第一个取舍是“重原理还是重操作”。我的选择是两者都要但顺序是先操作后原理。比如讲内存管理我不会一上来就讲伙伴系统和slab分配器的数据结构而是先让你用/proc/meminfo和/proc/slabinfo看到实际的内存分布然后再解释这些数字是怎么来的。这样你学的时候有抓手不会觉得在啃天书。第二个取舍是“讲哪个版本的内核”。内核版本差异很大2.6和5.x的很多机制完全不同。我的选择是以5.x和6.x为主因为这是当前主流发行版和嵌入式平台使用的版本。但对于一些经典机制比如CFS调度器我会追溯到它引入的版本讲清楚演进的脉络。这样你既能看到当前的状态也能理解为什么变成这样。第三个取舍是“要不要讲代码”。我的选择是讲关键代码片段但不逐行注释。内核代码量太大逐行讲既没必要也不现实。我的做法是先讲清楚一个机制的流程和数据结构然后贴出核心的几十行代码标注关键的函数调用和数据结构字段让你能把理论和代码对应起来。如果你想深入看完整实现可以顺着这些线索自己去读源码。3. 核心模块的拆解与实操要点3.1 内核源码结构与编译体系很多人第一次打开内核源码目录的时候是懵的arch、block、crypto、drivers、fs、include、init、ipc、kernel、lib、mm、net、scripts、security、sound、tools、usr、virt这么多目录每个里面又是层层嵌套的子目录完全不知道从哪儿看起。我的建议是先搞清楚几个核心目录的职责。arch是体系结构相关的代码比如x86、arm、arm64、riscv每个架构下面又有boot、kernel、mm、include等子目录。kernel是核心的通用代码进程调度、中断处理、时间管理、同步机制都在这里。mm是内存管理包括页分配、slab分配器、虚拟内存、页缓存。fs是文件系统包括VFS抽象层和具体的文件系统实现。drivers是设备驱动占了源码的很大一部分但学习的时候可以按需查看。net是网络协议栈从socket层到TCP/IP实现再到网卡驱动。include是头文件linux子目录下是内核内部使用的uapi子目录下是暴露给用户空间的。编译体系这块核心是Kconfig和Makefile。Kconfig定义了配置选项和依赖关系Makefile定义了编译规则。很多人做内核裁剪的时候只知道在make menuconfig里勾选但不知道选项之间的依赖关系是怎么定义的。比如你关掉了一个选项结果发现另一个选项自动被关掉了这就是Kconfig里的depends on和select在起作用。理解这套机制之后你就能预判裁剪的结果而不是反复试错。实操的时候我建议先在一个虚拟机上完整走一遍编译流程。从下载源码、配置、编译到安装每一步都手动执行不要用发行版提供的脚本。这样你会遇到各种报错比如缺少依赖库、交叉编译工具链配置错误、内核配置不兼容等等。解决这些报错的过程就是理解编译体系的过程。注意编译内核之前一定要确认磁盘空间充足完整编译一次5.x内核大约需要15到20GB的空间如果开启了调试信息还会更多。另外第一次编译建议用make defconfig生成默认配置不要一上来就手动裁剪否则很容易因为关掉了某个关键选项导致编译失败或者启动不了。3.2 启动流程与初始化机制内核启动流程是理解整个系统运作的入口。从Bootloader把控制权交给内核开始到第一个用户空间进程init启动中间经历了一系列复杂的初始化步骤。这个过程搞清楚之后你就能理解很多系统行为的根源比如为什么某些驱动必须在特定阶段加载为什么启动参数会影响硬件初始化。启动流程大致可以分为几个阶段首先是解压阶段如果内核是压缩的会先由解压程序把内核解压到内存中。然后是汇编阶段的初始化设置页表、开启分页、切换到保护模式或长模式。接着是C语言的初始化start_kernel函数是核心入口它会依次调用各个子系统的初始化函数。最后是init进程的启动内核会尝试执行/sbin/init、/etc/init、/bin/init、/bin/sh找到哪个就执行哪个。start_kernel这个函数值得仔细看它里面的调用顺序反映了各个子系统的依赖关系。比如setup_arch会先执行因为体系结构相关的初始化是基础。然后是mm_init内存管理必须先初始化后面的子系统才能分配内存。接着是sched_init调度器初始化之后才能创建内核线程。再往后是rest_init它会创建kernel_init和kthreadd两个内核线程前者最终变成用户空间的init进程后者是所有内核线程的父线程。实操中经常遇到的问题是关于启动参数的。比如你在调试一个嵌入式板子串口没有输出这时候你需要检查bootargs里的console参数是否正确。又比如系统启动到某个阶段卡住了你可以通过initcall_debug参数让内核打印每个初始化函数的执行情况从而定位是哪个驱动出了问题。提示如果你在做嵌入式开发建议把启动流程中的每个initcall级别都搞清楚。内核把初始化函数分成了多个级别从early_initcall到late_initcall不同级别的函数在启动过程中的执行时机不同。理解这个分级机制你就能控制自己写的驱动在什么阶段初始化避免因为初始化顺序不对导致的问题。3.3 进程管理与调度机制进程管理是内核最核心的功能之一。从用户空间看进程就是一个正在运行的程序从内核角度看进程是一组资源地址空间、文件描述符、信号处理等加上一个执行上下文寄存器状态、栈、调度信息。理解进程管理关键是要搞清楚task_struct这个数据结构它包含了进程的所有信息。task_struct很大在64位系统上可能有几KB。它里面有几个关键字段需要重点关注state表示进程状态运行、可中断睡眠、不可中断睡眠、停止、僵尸pid和tgid分别表示进程ID和线程组IDmm指向内存描述符files指向打开文件表sighand指向信号处理表sched_entity是调度实体包含了调度相关的信息。调度器这块当前主流的是CFS完全公平调度器。CFS的核心思想是用红黑树来管理可运行的进程每个进程有一个虚拟运行时间vruntime调度器总是选择vruntime最小的进程来运行。vruntime的增长速度和进程的权重成反比权重又和nice值相关。这样nice值低的进程优先级高vruntime增长慢获得更多的CPU时间nice值高的进程vruntime增长快获得的CPU时间少。实操中你可以通过/proc/[pid]/sched查看一个进程的调度信息包括vruntime、se.sum_exec_runtime实际运行时间、nr_switches上下文切换次数等。如果你发现某个进程的vruntime增长异常快可能是它的nice值太高或者它在等待某个资源导致频繁睡眠。注意调整进程优先级的时候不要只改nice值还要考虑调度策略。Linux支持多种调度策略SCHED_NORMALCFS、SCHED_BATCH批处理、SCHED_IDLE空闲时运行、SCHED_FIFO实时先进先出、SCHED_RR实时轮转。实时调度策略的优先级高于普通调度策略如果设置不当可能导致系统卡死。我见过有人把某个进程设成SCHED_FIFO并且优先级设得很高结果这个进程死循环整个系统都没法响应了。3.4 内存管理与性能调优内存管理是内核最复杂的子系统之一也是面试和实际工作中问题最多的部分。从物理内存的页分配到虚拟内存的地址映射再到页缓存和交换机制每一层都有很多细节。物理内存管理的基础是伙伴系统。内核把物理内存分成一个个页通常4KB然后用伙伴系统来管理这些页的分配和释放。伙伴系统的核心思想是把空闲页按2的幂次方分组分配的时候如果当前大小的组没有空闲页就向上找更大的组拆分后分配释放的时候如果相邻的页也是空闲的就合并成更大的组。这样既能满足不同大小的分配需求又能减少外部碎片。在伙伴系统之上是slab分配器现在主流是SLUB。伙伴系统的最小分配单位是页但内核中很多数据结构很小比如一个task_struct可能只有几KB如果每次都分配一整页就太浪费了。slab分配器的作用就是把这些小对象缓存起来按对象大小分组管理分配的时候直接从缓存里取不用走伙伴系统。虚拟内存管理这块核心是页表。每个进程有自己的页表把虚拟地址映射到物理地址。页表是多级结构x86_64通常是四级页表PGD、PUD、PMD、PTE。地址转换的过程是从CR3寄存器拿到PGD的基地址然后逐级索引最后找到物理页帧号加上页内偏移得到物理地址。实操中排查内存问题常用的工具和文件有/proc/meminfo看整体内存使用情况/proc/[pid]/status看单个进程的内存使用/proc/[pid]/smaps看进程的详细内存映射/proc/slabinfo看slab缓存的使用情况vmstat看系统的内存和交换活动free看内存总量和可用量。提示/proc/meminfo里的Buffers和Cached经常让人困惑。Buffers是块设备读写使用的缓存Cached是文件内容缓存。这两个加起来就是页缓存的总量。很多人看到free命令输出里free列很小就紧张其实available列才是真正可用的内存它已经把可回收的页缓存算进去了。3.5 文件系统与IO栈文件系统这块理解VFS虚拟文件系统是关键。VFS是一个抽象层它定义了统一的接口让不同的文件系统ext4、xfs、btrfs、fat32等可以用同样的方式访问。VFS的核心数据结构有四个super_block表示一个已挂载的文件系统inode表示一个文件或目录的元数据dentry表示目录项路径中的一个组成部分file表示一个打开的文件。IO栈的层次也值得搞清楚。从用户空间调用read/write开始经过VFS层、文件系统层、页缓存层、块设备层最后到设备驱动层。每一层都有自己的处理逻辑和优化机制。比如页缓存层会缓存最近读写的文件内容如果命中缓存就直接返回不用访问磁盘。块设备层会用IO调度器来合并和排序IO请求减少磁盘寻道时间。实操中排查IO问题常用的工具有iostat看磁盘IO统计iotop看进程级别的IOblktrace跟踪块设备层的IO请求strace跟踪系统调用。如果你发现系统IO负载很高先用iostat -x 1看是哪个磁盘忙然后看%util和await指标。%util接近100%说明磁盘饱和await很高说明IO延迟大。接着用iotop看是哪个进程在大量读写最后用strace或者blktrace深入分析具体的IO模式。注意调整IO调度器的时候要区分场景。cfq完全公平队列适合桌面和交互式场景deadline适合数据库场景noop适合SSD和虚拟化场景。现在很多发行版默认用mq-deadline或者none对于NVMe设备。不要盲目照搬网上的调优参数要根据实际硬件和工作负载来测试。4. 常见问题与排查技巧实录4.1 内核问题定位的基本方法论内核问题排查和用户空间问题排查最大的区别是用户空间程序崩溃了会有core dump有堆栈信息有日志内核出问题了可能直接死机、重启什么线索都没有。所以内核问题排查更依赖前期的准备和系统化的方法。我的基本方法论是“先看现象再找线索最后验证假设”。现象包括系统是否还能响应是否有日志输出是否有内核警告或panic信息。线索包括dmesg输出、/var/log/messages、/var/log/kern.log、/proc和/sys下的相关文件。验证假设的方法包括调整内核参数、加载或卸载模块、使用ftrace或perf跟踪。一个常见的场景是系统负载很高但CPU使用率不高。这种情况通常是IO等待或者锁竞争导致的。先用vmstat 1看r列运行队列长度和b列阻塞进程数如果b列很高说明有进程在等待IO或者锁。然后用iostat -x 1看磁盘IO如果磁盘很忙那就是IO问题。如果磁盘不忙那可能是锁竞争需要用perf或者ftrace来跟踪。另一个常见场景是内存泄漏。用户空间的进程内存泄漏可以用valgrind但内核的内存泄漏需要看/proc/slabinfo和/proc/meminfo。如果Slab总量持续增长说明有内核对象泄漏。你可以对比不同时间点的/proc/slabinfo看哪个缓存的对象数在增加。找到可疑的缓存后可以用slabinfo的调试功能或者kmemleak来进一步定位。4.2 常见问题速查表问题现象可能原因排查方法解决思路系统启动卡住驱动初始化失败、根文件系统挂载失败、init程序找不到加initcall_debug参数看卡在哪个初始化函数检查bootargs中的root参数根据卡住的阶段调整配置或修复驱动系统负载高但CPU空闲IO等待、锁竞争、内存回收vmstat看b列iostat看磁盘perf top看热点函数优化IO模式、减少锁竞争、调整内存参数内存持续增长内核对象泄漏、页缓存增长、用户进程泄漏/proc/slabinfo对比/proc/meminfo看Slab和Cachedps看进程内存定位泄漏对象调整缓存回收策略修复用户程序网络丢包网卡缓冲区满、协议栈处理不过来、防火墙规则netstat -s看统计ethtool -S看网卡统计ss -s看socket统计调整缓冲区大小、优化协议栈参数、检查防火墙磁盘IO慢磁盘饱和、IO调度器不合适、文件系统碎片iostat -x看%util和awaitblktrace看IO模式更换调度器、调整读写模式、整理碎片内核panic空指针解引用、内存越界、硬件故障看panic信息中的调用栈dmesg看之前的警告根据调用栈定位代码检查硬件更新驱动4.3 几个容易踩的坑第一个坑是“盲目调参”。网上有很多内核调优的文章列了一堆sysctl参数和值但没说适用场景。我见过有人把vm.swappiness设成0结果内存不足的时候系统直接OOM而不是用交换空间。swappiness控制的是内核使用交换空间的倾向设成0只是“尽量不用”不是“绝对不用”。在内存紧张的场景下适当使用交换空间反而能避免OOM。第二个坑是“忽略版本差异”。内核版本之间的差异很大比如cgroup的v1和v2iptables和nftablesdevicetree的绑定规则变化等等。你在网上找到的配置或者代码可能只适用于特定版本。用之前一定要确认版本兼容性或者查一下对应版本的文档。第三个坑是“不看日志”。很多人遇到问题第一反应是重启而不是看日志。dmesg里有很多有用的信息比如硬件错误、驱动加载失败、文件系统警告等等。养成看日志的习惯很多问题在变成故障之前就能发现。提示如果你在做嵌入式开发建议在板子上保留一个串口控制台并且把内核日志级别调低比如loglevel8这样能看到更多的调试信息。另外printk的时间戳格式可以调整用printk.time1可以显示每个消息的时间方便分析时序问题。5. 工具链与调试手段的选型建议5.1 静态分析工具静态分析工具可以在不运行代码的情况下检查代码问题适合在开发阶段使用。常用的有sparse、smatch、coccinelle、checkpatch.pl。sparse是内核自带的静态分析工具主要检查类型问题、锁问题、地址空间标注等。比如它会检查__user指针是否被正确使用__iomem指针是否被正确访问。编译内核的时候加C1或者C2参数就会调用sparse。smatch是在sparse基础上发展起来的检查规则更多包括空指针解引用、缓冲区溢出、整数溢出等。它需要单独安装然后在内核编译的时候指定CHECKsmatch。coccinelle是一个模式匹配工具可以用来查找和修复代码中的常见错误模式。比如查找所有忘记释放锁的代码路径或者查找所有使用kmalloc但没有检查返回值的代码。它的规则用SmPL语言编写内核源码里自带了很多规则。checkpatch.pl是检查代码风格的提交内核补丁之前必须跑一遍。它会检查缩进、行长度、注释风格、提交信息格式等。虽然严格但能避免很多低级问题。5.2 动态跟踪工具动态跟踪工具可以在运行时观察内核行为是排查问题的利器。常用的有ftrace、perf、eBPF、SystemTap。ftrace是内核自带的跟踪框架功能强大但配置稍复杂。它可以跟踪函数调用、中断、调度事件、IO事件等。基本用法是挂载tracefs选择跟踪器设置过滤条件读取trace文件。比如跟踪所有kmalloc调用echo kmalloc set_ftrace_filterecho function current_tracer然后cat trace。perf是性能分析工具可以采样CPU周期、缓存命中、分支预测等硬件事件也可以跟踪软件事件。常用的命令有perf top实时看热点函数、perf recordperf report采样分析、perf trace跟踪系统调用、perf stat统计事件计数。eBPF是当前最热门的动态跟踪技术它允许你在内核中运行沙箱程序可以安全地访问内核数据结构和事件。常用的工具有bpftrace类似awk的脚本语言、bccPython库、libbpfC库。比如用bpftrace跟踪所有打开文件的系统调用bpftrace -e tracepoint:syscalls:sys_enter_openat { printf(%s %s\n, comm, str(args-filename)); }。SystemTap是另一个动态跟踪工具语法类似awk功能也很强大。不过它需要编译内核模块在某些环境下可能受限。5.3 调试器与崩溃分析gdb是用户空间调试器但也可以用来调试内核。配合qemu可以在虚拟机上单步调试内核。基本流程是编译内核时开启调试信息CONFIG_DEBUG_INFOy用qemu -s -S启动虚拟机然后用gdb vmlinux连接设置断点单步执行。crash是专门分析内核崩溃转储的工具。当内核panic时如果配置了kdump会生成一个vmcore文件。用crash vmlinux vmcore打开可以查看崩溃时的寄存器状态、堆栈、内存、进程列表等。常用的命令有bt堆栈回溯、log内核日志、ps进程列表、kmem内存信息。drgn是一个新的内核调试工具用Python编写可以脚本化地分析内核状态。它比crash更灵活适合写自动化分析脚本。注意使用crash分析vmcore的时候vmlinux必须是和崩溃内核完全对应的版本包括编译配置和编译时间。如果版本不匹配crash可能无法正确解析符号和数据结构。所以生产环境上部署内核的时候一定要保存好对应的vmlinux和System.map文件。6. 从学习到实战的转化路径6.1 怎么把内核知识用到日常工作中学内核知识最怕的就是“学完用不上”。我自己的经验是不要为了学而学而是带着问题去学。比如你发现系统在高峰期响应变慢那就去研究调度器和内存管理你发现磁盘IO很高那就去研究文件系统和IO栈你发现网络延迟大那就去研究网络协议栈。一个具体的例子我之前遇到一个服务在高并发下响应时间波动很大的问题。用perf分析发现大量时间花在__mutex_lock_slowpath上说明有锁竞争。进一步用ftrace跟踪发现是某个全局锁被频繁争抢。解决方案是把全局锁改成每CPU变量或者读写锁减少竞争。这个过程中我用到了调度器知识理解为什么锁竞争会导致响应时间波动、内存管理知识理解每CPU变量的分配和使用、同步机制知识理解不同锁类型的适用场景。另一个例子在做嵌入式设备启动优化的时候我发现启动时间比预期长了2秒。用initcall_debug参数打印每个初始化函数的耗时发现是一个驱动在初始化的时候做了大量的延时操作。进一步看代码发现它在等待硬件就绪的时候用了msleep(100)而且循环了20次。改成中断驱动的方式后启动时间缩短了1.8秒。这个过程中我用到了启动流程知识理解initcall的执行顺序、驱动模型知识理解中断和轮询的区别、时间管理知识理解msleep和udelay的区别。6.2 持续学习的资源和方法内核社区的活动很活跃保持学习的最好方式是跟踪社区动态。LKMLLinux内核邮件列表是核心开发讨论的地方虽然邮件量很大但可以只看自己关心的子系统。lwn.net是内核新闻和分析网站文章质量很高适合了解新特性和社区动态。kernelnewbies.org适合初学者有入门指南和常见问题解答。源码阅读方面我建议从自己熟悉的子系统开始。比如你平时用网络编程多那就从net目录开始你做存储相关的工作那就从fs和block目录开始。不要一上来就啃kernel/sched或者mm这些是核心中的核心代码复杂容易劝退。实践方面我建议自己编译和运行内核。可以从make defconfig开始然后逐步修改配置观察行为变化。也可以写一些简单的内核模块比如字符设备驱动、proc文件系统接口、内核线程等。写模块的过程中会遇到各种问题解决这些问题的过程就是学习的过程。提示如果你在学内核的过程中遇到问题不要急着去网上搜答案。先自己看代码、看文档、做实验尝试自己解决。实在解决不了再去搜但搜到答案之后要理解为什么而不是直接复制粘贴。自己解决一个问题的收获比看十篇文章都大。6.3 这个专栏后续的更新计划这个总目录会持续更新目前规划的更新方向有几个。一是补充更多的实操案例特别是故障排查和性能调优的完整过程从现象到分析到解决一步步展示思路和方法。二是增加视频演示有些操作和工具的使用看视频比看文字更直观。三是整理常见面试题的深入解析不是给标准答案而是讲清楚背后的原理和关联知识。更新频率上我尽量保持每周至少一篇分篇的更新。如果某个知识点有重大变化比如内核版本升级导致机制改变我会优先更新对应的分篇。总目录本身也会定期调整增加新的章节调整学习路径优化导航结构。如果你有特别想了解的知识点或者在实际工作中遇到了内核相关的问题欢迎反馈。我会根据反馈调整更新计划优先写大家最需要的内容。这个专栏的目标是成为一个真正有用的内核学习资源而不是一个写完就放在那里的文档。
返回列表