搜索
高级检索
高级搜索
书       名 :
著       者 :
出  版  社 :
I  S  B  N:
文献来源:
出版时间 :
独辟蹊径品内核:Linux内核源代码导读
0.00    
图书来源: 浙江图书馆(由图书馆配书)
  • 配送范围:
    全国(除港澳台地区)
  • ISBN:
    9787121085154
  • 作      者:
    李云华编著
  • 出 版 社 :
    电子工业出版社
  • 出版日期:
    2009
收藏
编辑推荐
  较新的内核版本:本书使用的内核版本为2.6.24。
  独特的写作手法:本书在讨论“How”的基础上,力求进一步探究“Why”。
  “授人以渔”的写作宗旨:Linux内核处于飞速发展中,任何资料都无法覆盖内核的方方面面。配收以笔者学习过程的疑问和经验为基础,融会贯通于各个章节,毫无保留地就如何学习内核,如何分析内核进行了大量且大胆的探讨,从而力求体现本书的写作宗旨——“授人以渔”。
展开
作者简介
  李云华,是一名内核技术的狂热爱好者,长期从事操作系统内核、计算机网络、设备驱动程序、以及嵌入系统方面的开发和研究。拥有丰富的设备驱动开发、网络优化、内核及驱动移植、嵌入式系统构建等方面的开发经验。对Windows内核驱动及Linux内核驱动均有丰富的开发经验及心得体会。
展开
内容介绍
  《独辟蹊径品内核:Linux内核源代码导读》根据最新的2.6.24内核为基础。在讲述方式上,《独辟蹊径品内核:Linux内核源代码导读》注重实例分析,尽量在讨论“如何做”的基础上,深入讨论为什么要这么做,从而实现《独辟蹊径品内核:Linux内核源代码导读》的写作宗旨:“授人以渔”。在内容安排上,《独辟蹊径品内核:Linux内核源代码导读》包含以下章节x86硬件基础;基础知识;Linux内核Makefile分析;Linux内核启动;内存管理;中断和异常处理;系统调用;信号机制在类UNIX系统中;时钟机制;进程管理;调度器;文件系统;常用内核分析方法。
  《独辟蹊径品内核:Linux内核源代码导读》适合初、中级Linux用户、从事内核相关开发的从业人员,也可以作为各类院校相关专业的教材及Linux培训班的教材,也可作为Linux内核学习的专业参考书。
展开
精彩书摘
  第1章 x86硬件基础
  如果你是一个Linux内核初学者,你一定常常遇到:保护模式,分段机制,分页机制,段地址,线性地址,中断门,调用门,局部描述符,全局描述符,等等这样的名词。这些概念常常把初学者弄得“云里来,雾里去”。你会常常感慨,Intel为什么要设计这么复杂的概念呢?仅仅是一个地址机制,就常常让初学者打开书本,发现自己会算了,可是一旦关上书本,换个例子,又迷惑了。
  事实上这些机制的背后都有它的缘由,任何一个复杂的设计都是由一个简单的设计发展起来的,当简单的设计满足不了实际需要时,就会一步一步地革新,直到问题被圆满地解决。因此理解一个“复杂”的东西的最好方式不是去记住它,而是要从最简单的地方入手,一步一步地推敲,简单的设计在现实中会遇到什么问题?又该如何解决这个问题?再联系到你现在要理解的复杂的例子,慢慢地建立起一条完整的线索,这样知识不会出现断层,你也不需要一次跨越一个鸿沟,一切都水到渠成。例如:在学习保护模式中的地址机制时,你一定会感觉为什么要这么复杂呢?实模式不是很简单吗?既然实模式简单,那么不妨想想,如果使用实模式会遇到什么问题呢?把这些问题都一一列出来,再结合现有机制,你就会很自然的理解为什么需要这么做了。本章将试图让读者看到这些概念背后的“为什么”。
  1.1  保护模式
  1.1.1 分页机制
  内存按字节编址,每个地址对应一个字节的存储单元,早期的程序直接使用物理地址。在单任务操作系统时代,物理内存被划分为两部分,一部分地址空间由操作系统使用,另外一部分由应用程序使用。到了多任务时代,由于程序中的全局变量,起始加载地址是在链接期决定的。如果直接使用物理地址,则很可能有多个起始地址一致的应用程序需要同时被加载运行,这就需要把冲突的程序加载到另外的地址上去,然后重新修正程序中的所有相关的全局符号的地址。然而在早期的计算机系统上内存容量十分有限,即便是通过重定位解决了加载地址冲突的问题,由于内存大小的限制,能够同时加载运行的程序仍然十分有限。而在多任务系统上,某些进程在部分时间内处于等待状态,于是人们很自然地想到,当内存不够的时候把处于等待状态的进程换入磁盘,腾出一些内存空间来加载新程序。这又带来了新的问题:每次腾出来的空间地址可不是固定不变的,这就意味着把磁盘上的内容加载进来的时候,又要重新修正程序中的相关地址,在每次换入换出的过程中要不断地修正相关程序的地址。而且还有一个更为严重的问题:假设进程A出现一个错误,对某个物理地址进行了写入操作,恰好这个地址又属于进程B,当进程B被调度运行的时候,必然会出现错误。很难想象一个软件产品的BuG却导致用户抱怨另外一个软件产品。于是虚拟内存技术发展起来。在虚拟内存中,程序代码中访问的不再是物理地址,而是虚拟地址。
  以32位系统为例,每一个进程有4GB的虚拟地址空间,每个进程中有一个表,它记录着每个虚拟地址对应的物理地址是多少,这样当程序加载的时候,可以先分配好物理内存,然后把物理内存的地址填入这个表里面,这样进程之间互不影响。假设程序A和B都是要求在地址BASE处加载(程序中使用的都是虚拟地址。),由于每个进程都有4GB的私有虚拟地址空间,因此两个进程没有加载冲突。操作系统分配的物理地址分别是A1和B1,然后A1和B1起始的物理内存地址分别被填入两个进程虚拟地址映射表中,从而建立虚拟地址和物理地址的一一映射关系。当进程A访问虚拟地址BAsE+X的时候,由于MMu的硬件支持,硬件自动查找进程A的地址映射表,从而访问到物理地址为A1+x的内存单元。同理,当进程B访问虚拟地址为BAsE+x的时候,MMU自动查找进程B的地址映射。表,从而访问到B1+X的内存单元。当然,实际上的虚拟地址机制比这个复杂得多,但是在对它又了总体认识之后,再来学习一个实际的例子就要简单得多了。接下来就以32位的x86系统为例,进一步介绍虚拟内存机制。
  每个进程拥有4GB的虚拟地址空间,每个字节的虚拟地址可以通过地址映射表映射到一个字节的物理地址上面去。因此这个映射表本身必然要占据很大的内存空间,如何设计映射表成为问题的关键。如果在虚拟地址映射表中为每一个字节建立映射关系,那么映射4GB的虚拟地址需要230×4B(32位系统地址为4Byte)的内存。可见简单的一一填表映射是不能满足现实要求的。为了要减少虚拟地址映射表项占用的内存空问,所有操作系统都采用了页式管理。把物理内存划分为4KB,8KB或者16KB大小的页,这样每个页面在虚拟地址映射表中仅仅占用4Byte的内存。以4KB的页大小为例,4GB的虚拟地址空间有220个页面,那么映射4GB空间的映射表仅仅需要220×4B(32系统地址为4Bvte)的内存。
  其映射原理如图1.1所示:程序要访问的地址是0x12345A10,cPu中的MMu首先找到这个进程的虚拟地址映射表,其起始物理地址为0x10000000。在4KB页大小的情况下,4GB虚拟地址空间含有220个页面,只需要20位就可以表示220的大小了,所以虚拟地址的高20位0x12345作为虚地址映射表中的索引,在32位系统上虚地址映射表中的每一项是4个字节,所以MMu根据地址0X10000000+0X123454取得虚拟地址0x12345A10对应的物理页面起始地址为0x54321000,该地址的低12位总是为0,这是由于每一个4KB.大小的物理页面总是在4KB的边界上对齐的。而虚地址Oxl2345A10中的低12位被用伽页内偏移量,最终虚地址0x12345A10对应的物理地址为0x54321000+A10,而CPU访问到的内容是0x12345678。
  由于页大小为4KB,虚地址表中的表项低12位总是为0,因此可以把低12位用来做标识位。例如把第0位用做存在位,当第0位为1时表示该页面在物理内存中,反之表示该页面不在物理内存中。假设一个进程要占用10MB的内存空间,在进程初始化的时候,虚地址映射表初始化为0,在内存不足的情况下,系统只分配了5MB的内存,这5MB内存的物理地址被填入到映射表中,同时表项中最低位被设置成1,当进程访问到另外5MB的虚地址的时候,MMU在查表时发现最低位为0,于是触发一个缺页中断,这个时候,系统缺页中断处理例程再分配内存页面,同时更新相应的映射表项,之后程序就可以正常运行了。
  同理,还可以把一位划分出来作为读写位,如果对一个地址进行写入操作,MMu在查表的时候会根据其读写位判断是否允许写入。几乎每一个程序员都知道访问NuLL指针时,一定会出错,那么操作系统是如何捕捉到这个错误的呢?地址0(NULL)实实在在地对应了内存中的一个物理内存地址,如何根据一个地址来判断指针是不是合法的呢?各个操作系统都保证在一个进程中虚拟地址从0开始的某一段区域是不映射的,其页表项为0。例如windows中把0~64K的地址区域划分到NULL指针区而不被映射。因此访问这部分地址的时候必然会触发缺页中断,这个时候操作系统就可以判断出这个地址是否落在NuLL指针区内。否则无论像malloc这一类的函数返回的指针是0还是其他的值,都无法判断分配成功或是失败。
展开
目录
第1章 x86硬件基础1
1.1 保护模式1
1.1.1 分页机制1
1.1.2 分段机制7
1.2 系统门13
1.3 x86的寄存器14
1.4 典型的PC系统结构简介16

第2章 基础知识18
2.1 AT&T与Intel汇编语法比较18
2.2 gcc内嵌汇编20
2.3 同步与互斥25
2.3.1 原子操作25
2.3.2 信号量27
2.3.3 自旋锁29
2.3.4 RCU机制35
2.3.5 percpu变量39
2.4 内存屏障41
2.4.1 编译器引起的内存屏障41
2.4.2 缓存引起的内存屏障44
2.4.3 乱序执行引起的内存屏障47
2.5 高级语言的函数调用规范49

第3章 Linux内核Makefile分析52
3.1 Linux内核编译概述52
3.2 内核编译过程分析54
3.3 内核链接脚本分析62

第4章 Linux内核启动65
4.1 BIOS启动阶段65
4.2 实模式setup阶段67
4.3 保护模式startup_3277
4.4 内核启动start_kernel()84
4.5 内核启动时的参数传递90
4.5.1 内核参数处理91
4.5.2 模块参数处理95

第5章 内存管理99
5.1 内存地址空间99
5.1.1 物理内存地址空间99
5.1.2 虚拟地址空间101
5.2 内存管理的基本数据结构104
5.2.1 物理内存页面描述符104
5.2.2 内存管理区106
5.2.3 非一致性内存管理108
5.3 内存管理初始化109
5.3.1 bootmemalloctor的初始化109
5.3.2 页表初始化115
5.3.3 内存管理结构的初始化118
5.4 内存的分配与回收127
5.4.1 伙伴算法127
5.4.2 SLUB分配器138

第6章 中断与异常处理152
6.1 中断的分类152
6.2 中断的初始化156
6.2.1 异常初始化156
6.2.2 中断的初始化160
6.2.3 中断请求服务队列的初始化167
6.3 中断与异常处理171
6.3.1 特权转换与堆栈变化171
6.3.2 中断处理172
6.3.3 异常处理177
6.4 软件中断与延迟函数180
6.4.1 softirq180
6.4.2 tasklet185
6.5 中断与异常返回187
6.6 中断优先级回顾191
6.7 关于高级可编程中断控制器192
6.7.1 APIC初始化193

第7章 信号机制199
7.1 信号机制的管理结构200
7.2 信号发送204
7.3 信号处理210

第8章 系统调用220
8.1 Libc和系统调用220

第9章 时钟机制226
9.1 clocksource对象227
9.1.1 clocksource概述227
9.1.2 clocksource初始化228
9.2 tickless机制232
9.2.1 tickless由来232
9.2.2 clockeventdevice对象概述234
9.2.3 clockeventdevice对象的初始化236
9.3 High-ResolutionTimers247
9.3.1 High-ResolutionTimers管理结构247
9.3.2 High-ResolutionTimers初始化252
9.3.3 High-ResolutionTimers操作258
9.4 时钟中断处理268
9.4.1 时钟维护276
9.4.2 进程时间信息统计281
9.5 软件定时器283
9.5.1 基本管理结构283
9.5.2 初始化284
9.5.3 注册与过期处理287

第10章 进程管理295
10.1 进程描述符296
10.1.1 进程状态297
10.1.2 进程标识299
10.1.3 进程的亲缘关系300
10.1.4 进程的内核态堆栈301
10.1.5 进程的虚拟内存布局302
10.1.6 进程的文件信息305
10.2 进程的建立306
10.2.1 建立子进程的task_struct对象308
10.2.2 子进程的内存区域315
10.2.3 子进程的内核态堆栈323
10.2.4 0号进程的建立325
10.3 进程切换327
10.4 进程的退出331
10.4.1 do_exit函数331
10.4.2 task_struct结构的删除334
10.4.3 通知父进程335
10.5 do_wait()函数338
10.6 程序的加载344

第11章 调度器351
11.1 早期的调度器351
11.2 CFS调度器的虚拟时钟353
11.3 CFS调度器的基本管理结构357
11.4 CFS调度器对象359
11.5 CFS调度操作360
11.5.1 update_curr()函数360
11.5.2 scheduler_tick()函数362
11.5.3 put_prev_task_fair()函数364
11.5.4 pick_next_task()函数366
11.5.5 等待和唤醒操作368
11.5.6 nice系统调用373

第12章 文件系统376
12.1 Ext2的磁盘结构376
12.2 Ext2的内存结构385
12.3 虚拟文件系统的管理结构387
12.3.1 文件系统对象388
12.3.2 VFS的超级块389
12.3.3 VFS的inode结构400
12.3.4 VFS的文件对象406
12.3.5 VFS的目录对象409
12.3.6 VFS在进程中的文件结构412
12.4 文件系统的挂载413
12.5 路径定位425
12.6 文件打开与关闭441
12.7 文件读写449
12.7.1 缓冲区管理449
12.7.2 文件读写操作分析456

第13章 常用内核分析方法471
13.1 准确定位同名宏及结构体471
13.2 准确定位同名函数473
13.3 利用linkmap文件定位全局变量474
13.4 准确定位函数调用线索476
13.5 SystemTap在代码分析中的使用479
展开
加入书架成功!
收藏图书成功!
我知道了(3)
发表书评
读者登录

请选择您读者所在的图书馆

选择图书馆
浙江图书馆
点击获取验证码
登录
没有读者证?在线办证