没有合适的资源?快使用搜索试试~ 我知道了~
Linux内核阅读心得体会——pdf高清版
5星 · 超过95%的资源 需积分: 10 43 下载量 133 浏览量
2013-06-17
16:31:24
上传
评论
收藏 646KB PDF 举报
温馨提示
试读
71页
一篇linux内核的阅读感悟,对linux感兴趣的可以看一下。作者参考的内核版本为2.6.13
资源推荐
资源详情
资源评论
Table of Contents
读核感悟.......................................................................2
读核感悟-Linux 内核启动-内核的生成...........................................2
读核感悟-Linux 内核启动-从 hello world 说起...................................3
读核感悟-Linux 内核启动-BIOS.................................................5
读核感悟-Linux 内核启动-setup 辅助程序........................................6
读核感悟-Linux 内核启动-内核解压缩...........................................8
读核感悟-Linux 内核启动-开启页面映射.........................................9
读核感悟-Linux 内核启动-链接脚本............................................11
读核感悟-伪装现场-系统调用参数.............................................13
读核感悟-伪装现场-fork()系统调用...........................................15
读核感悟-伪装现场-内核线程:...............................................17
读核感悟-伪装现场-信号通信.................................................19
读核感悟-kbuild 系统-内核模块的编译.........................................22
读核感悟-kbuild 系统-编译到内核和编译成模块的区别...........................24
读核感悟-kbuild 系统-make bzImage 的过程.....................................26
读核感悟-kbuild 系统-make menuconfig........................................31
读核感悟-文件系统-用 C 来实现面向对象........................................32
读核感悟-设计模式-用 C 来实现虚函数表和多态..................................32
读核感悟-设计模式-用 C 来实现继承和模板......................................33
读核感悟-设计模式-文件系统和设备的继承和接口...............................34
读核感悟-设计模式-文件系统与抽象工厂.......................................36
读核感悟-阅读源代码技巧-查找定义...........................................37
读核感悟-阅读源代码技巧-变量命名规则.......................................42
读核感悟-内存管理-内核中的页表映射总结.....................................43
读核感悟-健壮的代码-exception table-内核中的刑事档案.......................44
读核感悟-定时器-巧妙的定时器算法...........................................45
读核感悟-内存管理-page fault 处理流程.......................................45
读核感悟-文件读写-select 实现原理...........................................47
读核感悟-文件读写-poll 的实现原理...........................................49
1 功能介绍:.............................................................49
2 关键的结构体:.........................................................49
3 poll 的实现.............................................................49
4 性能分析:.............................................................50
读核感悟-文件读写-epoll 的实现原理..........................................50
1 功能介绍...............................................................50
2 关键结构体:...........................................................51
3 epoll_create 的实现.....................................................53
4 epoll_ctl 的实现........................................................53
5 epoll_wait 的实现.......................................................54
6 性能分析...............................................................54
读核感悟-同步问题-同步问题概述.............................................55
1 同步问题的产生背景.....................................................55
2 内核态与用户态的区别...................................................55
读核感悟-同步问题-内核态自旋锁的实现.......................................56
1 自旋锁的总述............................................................56
2 非抢占式的自旋锁........................................................56
3 锁的释放...............................................................57
4 与用户态的自旋锁的比较.................................................57
5 总结...................................................................58
读核感悟-内存管理-free 命令详解.............................................58
读核感悟-文件读写-2.6.9 内核中的 AIO.........................................59
1 AIO 概述................................................................59
2 内核态 AIO 的使用.......................................................61
读核感悟-文件读写-内核态 AIO 相关结构体......................................61
1 内核态 AIO 操作相关信息.................................................61
2 AIO 上下文:............................................................63
3 AIO ring...............................................................63
4 异步 I/O 事件的返回信息.................................................64
读核感悟-文件读写-内核态 AIO 创建和提交操作..................................65
1 AIO 上下文的创建-io_setup().............................................65
2 AIO 请求的提交:io_submit 实现机制......................................66
读核感悟-文件操作-AIO 操作的执行............................................66
1.在提交时执行 AIO........................................................66
2.在工作队列中执行 AIO....................................................66
3.负责 AIO 执行的核心函数 aio_run_iocb.....................................67
4 AIO 操作的完成..........................................................67
读核感悟-文件读写-内核态是否支持非 direct I/O 方式的 AIO.....................67
读核感悟
读核感悟-Linux 内核启动-内核的生成
这段时间在看《Linux 内核源代码情景分析》,顺便写了一些感悟。
。
读内核源代码是一件很有意思的事。它像一条线,把操作系统,编译原理,C 语言,
数据结构与算法,计算机体系结构等等计算机的基础课程串起来。
我看内核源代码是用 lxr+glimpse(不一定要自己架,可以直接访问校内外的 lxr 网
站)的。如果在 windows 下也可以用 source insight。以下的当前路径为内核源代码路径,
通常为/usr/src/linux。内核版本为 2.6.13,平台为 x86
好,让我们开始 Linux 内核之旅。
我们的出发点是在 CPU 加电的一刹那,系统处于 16 位实地址模式下,终点是内核开
始运行 start_kernel(),系统处于 32 位页式寻址的保护模式下。那时内核映象 bzImage 已
经解压完毕,运行于内核态。系统中已经有了一个叫 swapper 的 0 号进程,有自己的内核堆
栈,情况就相对好理解得多。(尽管与用户态程序相比,还要多操心不少事,包括对硬件的
直接操作,内核态各种数据结构的初始化,对页表的操作等等)。
不过,不妨先做些准备动作。
首先,什么是内核?
目前,只知道编译内核后,产生一个叫 bzImage 的压缩内核映象。它不同于任何普通
的可执行程序。我们甚至不知道它从哪里开始执行。只知道把它往/boot/下一放,往 boot
loader 的配置文件(例如 grub 的 menu.lst)中写上相关信息,机子就顺利启动了。
因此,我对它的生成过程产生了浓厚兴趣。于是,我查看了相关资料,最直接的资料
来自于 arch/i386/boot/下的 Makefile。从 Makefile 中可以知道。bzImage 的产生过程是这
样的:
不过我不满足于此。于是,我想到了去看 arch/i386/boot/下的 Makefile。从
arch/i386/boot/Makefile 和 arch/i386/boot/compressed/Makefile 中可以看出(具体过程
省略,)
1.先生成 vmlinux.这是一个 elf 可执行文件
2.然后 objcopy 成 arch/i386/boot/compressed/vmlinux.bin,去掉了原 elf 文件中的一些
无用的 section 等信息。
3.gzip 后压缩为 arch/i386/boot/compressed/vmlinux.bin.gz
4.把压缩文件作为数据段链接成 arch/i386/boot/compressed/piggy.o
5.链接:arch/i386/boot/compressed/vmlinux = head.o+misc.o+piggy.o
其中 head.o 和 misc.o 是用来解压缩的。
6.objcopy 成 arch/i386/boot/vmlinux.bin,去掉了原 elf 文件中的一些无用的 section 等
信息。
7.用 arch/i386/boot/tools/build.c 工具拼接 bzImage = bootsect+setup+vmlinux.bin
过程好复杂。
这里要介绍一下 objcopy 命令,它的作用是把一个 object 文件转化为另一种格式的
文件。在这里,objcopy 的作用就是去掉原来 elf 文件中的 elf header 和一些无用的
section 信息。为什么要这么做呢?因为 elf 文件中的 elf header 和一些 section 的作用是
告诉 elf loader 如何载入 elf 可执行文件。但是,linux 内核作为一种特殊的 elf 文件,需
要特殊折辅助程序去装载它。往往它的装载地址是固定的。这时,为了保证通用性而存在的
elf header 和一些 section 对内核的装载就没有意义了。加上为了使内核尽可能小,所以干
脆把这些信息去掉。
我们可以看一下 vmlinux 和 arch/i386/boot/compressed/vmlinux。用 file 命令查
看,它们也是 elf 可执行文件。只是没有 main 函数而已
参考:
Documentation/kbuild/makefiles.txt
Documentation/kbuild/modules.txt
读核感悟-Linux 内核启动-从 hello world 说起
内核是从哪里开始执行的呢?几乎任何一本 Linux 内核源代码分析的书都会给出详细
的答案。不过,我试图从一个不同的角度(一个初学者的角度)来叙述,而不是一上来就给
出答案。从熟悉的事物入手,慢慢接近陌生的事物,这是比较常见的思路。既然都是二进制
代码,那么不妨从最简单的用户态 C 程序,hello world 开始。说不定能找到共同点。恰好
我是一个喜欢寻根究底的人。也许,理解了 hello world 程序的启动过程,有助于更好地理
解内核的启动。
好,开始寻根究底吧。从普通的 C 语言用户态程序开始写。先写一个简单的 hello
world 程序。
/*helloworld.c*/
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
然后 gcc helloworld.c -o helloworld,一个最简单的 hello world 程序出现了。
它是从哪里开始执行的呢?这还不简单?main 函数么。地球人都知道。
为什么一定要从 main 函数开始呢?于是,我开始琢磨这个 hello world 程序。
file helloworld 可知,它是一个 elf 可执行文件。
反汇编试试。
objdump -d helloworld
反汇编的结果令人吃惊,因为出现了_start()等一堆函数。一定是 gcc 编译时默认链
接了一些库函数。
其实,只要运行 gcc -v helloworld.c -o helloworld 就会显示 gcc 详细的编译链接
过程。其中包括链接/usr/lib/下的 crti.o crt1.o crtn.o 等等文件。用 objdump 查
看,_start()函数就定义在 crt1.o 文件中。
那么 helloworld 的真正执行的入口在哪里呢?我们可以使用 readelf 来查看,看有
没有有用信息。
readelf -a helloworld
helloworld 作为一个 elf 文件,有 elf 文件头,section table 和各个 section 等
等。有兴趣可以去看看 elf 文件格式的文档。
用 readelf 可知,在 helloworld 的 elf 文件头的信息中,有这么一项信息:
入口点地址: 0x80482c0
可见,helloworld 程序的入口地址在 0x80482c0 处,而由 objdump 得:
080482c0 <_start>:
可见,_start()是 helloworld 程序首先执行的函数。_start()执行完一些初始化工
作后,经过层层调用,最终调用 main().可以设想,如果_start()里最终调用的是 foo(),
那么 C 程序的主函数就不再是 main(),而是 foo()了。
再进一步:helloworld 程序具体是如何执行的呢。我们只能猜测是由 bash 负责执行
的。然而具体看 bash 代码就太复杂了。我们可以用 strace 跟踪 helloworld 的执行。
strace ./helloworld
出来一大堆函数调用。其中第一个是 execve().这是一个关键的系统调用,它负责载
入 helloworld 可执行文件并运行。其中有很关键的一步,就是把用户态的 eip 寄存器(实
际上是它在内存中对应的值)设置为 elf 文件中的入口点地址,也就是_start()。具体可见
内核中的 sys_execve()函数。
由此可见,程序从哪里开始执行,取决于在刚开始执行的那一刻的 eip 寄存器的值。
而这个 eip 是由其它程序设置的,在这里,eip 是由 Linux 内核设置的。具体过程如下:
1.用户在 shell 里运行./helloworld。
2.shell(这里是 bash)调用系统调用 execve()。
3.execve 陷入到内核里执行 sys_execve(),把用户态的 eip 设置为_start()。
4.当系统调用执行完毕,helloworld 进程开始运行时,就从_start()开始执行
5.helloworld 进程最后才执行到 main()。
参考:elf 文件格式
http://www.skyfree.org/linux/references/ELF_Format.pdf
读核感悟-Linux 内核启动-BIOS
“真罗嗦,直接告诉我 Linux 下用 glibc 库编译出来的 C 程序真正的入口地址是
_start()不就行了么?”臭鸡蛋扑面而来。
嗯,我说了我只是想用一种特别的方式来叙述问题。我更看重探索的过程中体现的思
考方式以及其中的乐趣。
回到我们的主题。Linux 内核为什么不是从 main 函数开始执行?事实上,Linux 内核
源代码里有许多 main()函数,但仔细一看。他们都是运行在用户态的。其实,从上一节中
可以看到,main()函数只是一个符号而已。很多书上提到 start_kernel()。它类似于
main()。但正如调用 main()的是_start()。在 start_kernel 之前仍然有很多代码。所以内
核的真正入口并不是 start_kernel()。
真正决定程序执行入口的是载入程序。对普通的 C 程序 helloworld 来说,Linux 内核
(严格的说应该是 bash)负责设置 helloworld 的入口点,并且启动 helloworld 进程的执
行。
于是,问题出现了,Linux 内核的载入程序是什么呢?难道是自己载入自己?
这类类似的问题在计算机史上出现过很多次,比如,C 程序可以用 C 编译器来写,那
么,C 编译器用什么来写呢?当然,解决的方案有很多种,比如,用汇编语言写。那么汇编
器用什么写呢?可以用机器语言写。虽然是件痛苦的事,但是一想到能造福这么多人,(发
散一下,C 编译器可以编译出各种新的语言的编译器或者解释器如 perl,然后程序员们再用
perl 来编出各种复杂的系统),简直太伟大了,那位用机器语言写汇编器的程序员一定会浑
身干劲。
可以借鉴一下思路,这类问题的常见的解决方式是构造一个简单的系统来解决一个复
杂的系统的问题,如此往复,像滚雪球一下,最终把一个极为复杂的问题解决掉。
所以,很自然的想到,用一个简单的内核,(不,它仅仅是一段程序,甚至不能称之
为内核,因为它的功能很有限)来启动真正的内核。就像用一个小当量的原子弹来引爆氢弹
一样。
本着 KISS(keep it simple and stupid)的原则,你第一时间可能会想到 BIOS。BIOS
通常存在 ROM 上。随着 ROM 容量的扩展(达 1M 甚至更多)PC 上的 BIOS 功能已经很强大了,
包括了很多设备的驱动程序。不仅可以进行硬件的检测,还实现了基本的输入输出功能。
(basic input / output system,这也是它的本意)。开机时按 del 键出现的 BIOS 设置画
面就是 BIOS 的杰作。在 BIOS 上实现一个 OS 也不是不可能。事实上 DOS 就是在 BIOS 的基础
上实现的。
然而,BIOS 的一个致命的缺点是到目前为止它基本上只能在 16 位实地址模式下运
行,毕竟 ROM 的容量很有限。(当然也不绝对,BIOS 也提供了在保护模式下扫描 PCI 设备的
方法,大牛们 yy 一下实现一个保护模式下运行的 BIOS 的可行性。)而 CPU 刚加电时处在 16
位实地址模式下。它的另一个致命的缺点是太小。因为现代操作系统多种多样,BIOS 再强
大也无法把所有可能的情况都考虑进去。
不过即使这样,PC 机刚启动时,x86 CPU 仍然会自动从 BIOS 开始启动,这是由硬件
决定的,因为加电时,寄存器 CS 里的值为 0xffff,IP 里的值为 0。于是 CPU 从线性地址
0xffff0 处开始取指令。0xffff0 处是什么地方呢?
剩余70页未读,继续阅读
资源评论
- wujunqiang20082014-07-30挺不错的书
- kingbaby20lin2016-06-19不错,作者理解很到位
- 跃ge2014-03-24很好的一本书
- haitian1990ss2015-06-25挺好的资源,说的问题不多但是都是经常遇到的
sun_yg1988
- 粉丝: 0
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于STM32F103C8T6单片机蓄电池在线监测系统主板硬件(原理图+PCB)工程文件.zip
- mysql大纲资料.txt
- c++大纲资料.txt
- 效率工具bat脚本实现日志提取
- MyBatis 中动态 SQL 的示例
- STM8L101F3P6单片机+CC1100模块433M遥控器设计硬件(原理图+PCB)工程文件.zip
- 上传下载铁人下载系统 Liuxing 1.0-liuxing1.0.rar
- 南京邮电大学数学实验实力雄厚,凭借其优秀的师资力量、丰富的实践教学资源和卓越的科研成果,成为国内一流的数学实验教学和科研基地
- 【火爆朋友圈的今天吃什么源码 v1.0】随机的为用户带来每一天的用餐选择和推荐.rar
- MPU6050中文版数据手册
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功