内核初探1
主要是跟着这个star非常多的github项目学习 https://github.com/0voice/linux_kernel_wiki
其实笔者在学校课程中已经学习过OS相关概念,对linux内核也有一些理解,但是总是觉得学习的比较片面,不够系统。所以准备跟着这个项目进行学习。但是学习要有方法,对于这么多的内容,不可能全部都看,会的可以选择性的跳过,然后最好每个章节整理出知识点,这说明是你记住的东西。有些重点内容就要详细做笔记搞明白原理,有些偏概念的可以记录关键词,这样以后再遇到可以知道如果搜索。
同时第一遍学习会有很多细节的东西,这会消耗大量时间去理解,不妨学会跳过很花时间的地方,这才是第一遍学习应有的方式。这一点就像阅读里面的粗读和精读一样,无论学习什么东西都应该按照这种方式才能更好地推动。
Linux内核架构和工作原理
比较基础,感觉像是碎碎念,和我OS课上学的基础知识比较接近。对内核中每个大的方向做了一个绪论,里面有一个东西没有细看,就是platform机制。
- 使用ls命令看到的内核源代码的顶层目录结构,具体描述如下:
Linux内核源代码包括三个主要部分:
\1. 内核核心代码,包括第3章所描述的各个子系统和子模块,以及其它的支撑子系统,例如电源管理、Linux初始化等
\2. 其它非核心代码,例如库文件(因为Linux内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等
\3. 编译脚本、配置文件、帮助文档、版权说明等辅助性文件
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 ---- 帮助、说明文档。
Makefile系统文件详解
Makefile只了解一点点,趁学习这个顺便学了学,但是学这个目的只是了解makefile,能大致看懂makefile的含义就达到了我学习的目的,所以文章中会有一些高级用法,这里我直接选择了跳过。
Makefile规则
target ... : prerequisites ...
command
...
...
- target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
- prerequisites就是,要生成那个target所需要的文件或是目标。
- command也就是make需要执行的命令。(任意的Shell命令,但注意要有个tab)
这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites 中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。
默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解释这个文件。在这三个文件名中,最好使用“Makefile”这个文件名,因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用“GNUmakefile”,这个文件是GNU的make识别的。有另外一些make只对全小写的“makefile”文件名敏感,但是基本上来说,大多数的make都支持“makefile”和“Makefile”这两种默认文件名。
Makefile示例
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
-rm edit $(objects)
- 让make自动推导,只要make看到一个[.o]文件,它就会自动地把[.c]文件加在依赖关系中,如果make 找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。
- .PHONY意思表示clean是一个“伪目标”,。而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然,clean的规则不要放在文件的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放在文件的最后”。
make的工作方式
GNU的make工作时的执行步骤入下:(想来其它的make也是类似)
1、读入所有的Makefile。
2、读入被include的其它Makefile。
3、初始化文件中的变量。
4、推导隐晦规则,并分析所有规则。
5、为所有的目标文件创建依赖关系链。
6、根据依赖关系,决定哪些目标要重新生成。
7、执行生成命令。
1-5步为第一个阶段,6-7为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么, make会把其展开在使用的位置。但make并不会完全马上展开,make使用的是拖延战术,如果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。
书写规则
- make支持三种通配符:“*”,“?”和“[…]”
- 文件搜寻,特殊变量“VPATH”。但这部分我还没怎么注意过,以后要用到了再来深入学习看看是怎么个事
- 伪目标
书写命令
- 显示命令
- 命令执行
- 命令出错
- 嵌套执行make,在一些大的工程中,我们会把我们不同模块或是不同功能的源文件放在不同的目录中,我们可以在每个目录中都书写一个该目录的Makefile,这有利于让我们的Makefile变得更加地简洁,而不至于把所有的东西全部写在一个Makefile中,这样会很难维护我们的Makefile,这个技术对于我们模块编译和分段编译有着非常大的好处。
我们有一个子目录叫subdir,这个目录下有个Makefile文件,来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写:
subsystem:
cd subdir && $(MAKE)
使用变量
略
计算机Intel CPU体系结构分析
计算机组成原理课的回忆开始攻击我,纯纯的计组内容,很多细节不想再看了。CPU体系结构我觉得最重要的就是下面的过程:
取指令、指令译码、执行指令、访存取数、结果写回
IF、ID、EXE、MEM、WB
QEMU调试Linux内核环境搭建
之前编译过几次内核,可以直接看那里的笔记。这里记录一下一些启动选项的不同
-hda 中的镜像需要具有文件系统结构(如 EXT4)。
-initrd 的文件通常是 CPIO 压缩包,不需要文件系统元信息。
如果你的场景需要模拟一个传统 Linux 系统,-hda 是更好的选择。
如果需要快速测试或提供一个小型启动环境,-initrd 是更简便的方式。
补充,之前学IOT搭建arm架构环境时遇到过:
在ARM 架构下,还有一个重要的文件类型:设备树(Device Tree Blob,DTB)。它是一个二进制文件(通常以 .dtb 结尾),由设备树源文件(DTS,Device Tree Source)编译生成。ARM 架构广泛用于嵌入式设备,每个设备的硬件可能大不相同。为了避免为每种硬件都编译不同的内核,设备树机制被引入,内核通过 DTB 文件动态获取硬件信息