随笔分类 - Linux内核设计与实践
Linux Kernel Development 3 Edition
Rebert Love
陈莉君 康华 译
摘要:页高速缓存是linux内核实现磁盘缓存。它主要用来减少对磁盘的IO操作。具体地讲,是通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。16.1 缓存手段16.2 Linux页高速缓存16.2.1 address_space对象在页高速缓存中的页可能包含了多个不连续的物理磁盘块。Linux页高速缓存对被缓存的页面范围定义非常宽泛。address_space结构体是虚拟地址区间vm_area_struct的物理地址对等体。当一个文件可以被10个vm_area_struct结构体标识,那么这个文件只能有一个address_space数据结构——也就是文件可以有多个虚拟地址,但是
阅读全文
摘要:15.1 地址空间进程地址空间由进程可寻址的虚拟内存组成。每个进程都有一个32位或64位的平坦地址空间,空间的大小取决于体系结构。术语“平坦”指的是地址空间范围是一个独立的连续区间。一些操作系统提供了段地址空间,这种地址空间并非一个独立的线性区域,而是被分段的,现代采用虚拟内存的操作系统通常都使用平坦地址空间而不是分段式的内存模式。通常,每个进程都有唯一的这种平坦地址空间,一个进程的地址空间与另一进城的地址空间即使有相同的内存地址,实际上也互不相干,我们称这样的进程为线程。尽管一个进程可以寻址4GB的虚拟内存(32位),并不表示它有权访问所有的虚拟地址。可以被合法访问的地址空间称为内存区域。通
阅读全文
摘要:系统中能够随机访问固定大小数据片的硬件设备称作块设备,这些固定大小的数据片称为块。最常见的块设备是硬盘、还有软盘驱动器、光驱盒闪存等。他们都是以安装文件系统的方式使用的。字符设备按照字节流的方式有序访问,如键盘和串口。14.1 剖析一个块设备块设备中最小的可寻址单元是扇区。扇区大小一般是2的整数倍,最常见的是512字节。扇区的大小是设备的物理属性,扇区是所有块设备的基本单元——块设备无法对比它还小的单元进行寻址和操作,尽管许多块设备能够一次对多个扇区进行操作。很多CD-ROM盘的扇区都是2kB大小。虽然物理磁盘寻址按照扇区级别进行的,但是内核执行的所有磁盘操作都是按照块进行的。由于扇区是设备的
阅读全文
摘要:虚拟文件系统为用户空间程序提供了文件和文件系统相关的接口。通过虚拟文件系统,程序可以利用标准的Unix系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作。13.1 通用文件系统接口13.2 文件系统抽象层VFS抽象层之所以能衔接各种各样的文件系统,是因为它定义了所有文件系统都支持的、基本的、概念上的接口和数据结构。同时实际文件系统也将自身的诸如“如何打开文件”,“目录是什么”等概念在形式上与VFS的定义保持一致。13.3 Unix文件系统Unix使用了四种和文件系统相关的传统抽象概念:文件、目录项、索引节点和安装点。文件:文件其实可以做一个有序的字节串,字节串中第一个字节是文件的开
阅读全文
摘要:12.1 页内核用struct page 结构表示系统中的每个物理页struct page{ unsigned long flags;// 存放页的状态,包括页是否脏,是否锁定于内存中 acomic_t _count;// 页的引用计数。-1时,就说明当前内核没有引用这一页。 atomic_t _mapcount; unsigned long private; //指向拥有这个页的私有数据 struct address_space *mapping; //指向和这个页关联的address_space对象即页高速缓存对象 pgoff_t index; struct lis...
阅读全文
摘要:11.1 内核中时间的概念硬件为内核提供了一个系统定时器用以计算流逝的时间,该时钟在内核中可以看成是一个电子时间资源。系统定时器以某种频率自行触发时钟中断,该频率可以通过编程指定,称作节拍率。因为预编的节拍率对内核来说是可知的,所以内核知道连续两次时钟中断的间隔时间。这个间隔时间就称为节拍,等于节拍率分之一秒。利用时钟中断处理的工作:更新系统运行时间、更新实际时间、均衡调度各处理器上的运行队列、检查当前进程是否用尽了时间片、运行超时的动态定时器、更新资源消耗和处理器时间的统计值。11.2 节拍率:HZ系统定时器频率(节拍率)是通过静态预处理定义的,也就是HZ,在系统启动时按照HZ的值对硬件进行
阅读全文
摘要:10.1 原子操作10.1.1 原子整数操作typedef struct{ volatile int counter;}atomic_t;10.1.2 64位原子操作10.1.3 原子位操作10.2 自旋锁自旋锁最多只能被一个可执行线程持有。如果一个执行线程试图获得一个被已经持有的自旋锁,那么该线程就会一直进行忙循环等待锁重新可用。要是锁未被争用,请求锁的执行线程便立刻得到它,继续执行。自旋锁不应该被长期持有。还可以让请求线程睡眠,直到锁重新可用时再唤醒他。这样处理器不必循环等待,可以去执行其他代码。这里有两次明显的上下文切换,被阻塞的线程要换出和换入。因此,持有自旋锁的时间最好小于完成两次.
阅读全文
摘要:9.1 临界区和竞争条件 所谓临界区就是访问和操作共享数据的代码段。如果两个执行线程有可能处于同一个临界区中执行,那么这就是程序中包含一个bug,这种情况就是竞争条件。9.2.1 造成并发执行的原因 用户空间之所以需要同步,是因为用户程序会被调度程序抢占和重新调度,由于用户进程可能在任何时刻被抢占,而调度程序完全可能选择另一个高优先级的进程到处理器上执行,所以会使得一个程序处于临界区时被非自愿的抢占了。如果重新调度的程序也进入了同一个临界区,就会产生竞争条件。内核中有类似可能造成并发的原因:1、中断2、软中断和tasklet3、内核抢占4、睡眠以及与用户空间同步5、对称多处理9.3 死锁避..
阅读全文
摘要:中断处理程序的局限:1、中断处理程序以异步的方式执行,并且它有可能会打断其他重要代码的执行。2、如果当前有一个中断处理程序正在执行,最好的情况是,与该中断同级的其他中断会被屏蔽,最坏情况下,当前处理器上所有其他中断都会被屏蔽。3、中断处理程序往往需要对硬件进行操作,所以他们不能阻塞。这限制了他们所作的事情。8.1 下半部下半部的任务就是执行与中断处理密切相关但中断处理程序本身不执行的工作。中断处理程序注定要完成一部分工作:几乎都需要通过操作硬件对中断的到达进行确认,有时他还会从硬件拷贝数据。8.1.2 下半部的环境3、软中断和tasklet软中断是一组静态定义的下半部接口,有32个,可以在所有
阅读全文
摘要:7.1 中断中断使得硬件得以发出通知给处理器。中断本质上是一种特殊的电信号,由硬件设备发向处理器。处理器接收到中断后,会马上向操作系统反应此信号的到来,然后就由操作系统负责处理这些新到来的数据。硬件设备生成中断的时候并不考虑与处理器时间的同步——中断可以随时产生。因此内核随时可能因为新到来的中断而被打断。异常:与中断不同,它在产生时必须考虑处理器同步。异常也常常成为同步中断。在处理器执行到由于编程失误而导致的错误指令或执行期间出现特殊情况(如缺页),必须靠内核来处理的时候,处理器就会产生一个异常。在x86体系结构上如何通过软中断实现系统调用,那就是陷入内核,然后引起一种特殊的异常——系统调用处
阅读全文
摘要:6.1 链表链表和静态数组的不同之处在于,他所包含的元素都是动态创建并插入链表的,在编译时不必知道具体需要创建多少个元素。链表中每个元素的创建时间各不相同,所以他们在内存中无须占用连续内存区。因为元素不连续存放,所以各个元素需要通过某种方式被连接在一起。6.1.1 单向链表和双向链表6.1.2 环形链表6.1.3 沿链表移动沿链表移动只能是线性移动。如果需要随机访问数据,一般不使用链表。使用链表存放数据的理想情况是:需要遍历所有数据或需要动态添加或删除数据。6.1.4 链表在linux中的实现linux内核中的链表不是将数据结构塞入链表,而是将链表节点塞入数据结构。使用宏container_o
阅读全文
摘要:5.1 与内核通信 系统调用主要作用:1、它为用户空间提供了一种硬件抽象层接口。例如,当需要读写文件的时候,应用程序就可以不去管磁盘介质和类型,甚至不用去管文件所在的文件系统是哪种类型。2、系统调用保证了系统的稳定和安全。作为硬件设备和应用程序之间的中间人,内核可以基于权限、用户类型和其他一些规则对需要进行访问进行裁决。3、如果应用程序可以随意访问硬件而内核对此一无所知的话,几乎无法实现多任务和虚拟内存,当然也不可能实现良好的稳定性和安全性。在linux中,系统调用是用户空间访问内核的唯一手段;除了异常和陷入外,他们是内核唯一的合法入口。5.2 API、POSIX和C库 一般情况下,应用程..
阅读全文
摘要:调度程序负责决定哪个程序投入运行、何时运行以及运行多长时间。调度程序没有太复杂的原理。最大限度地利用处理器时间的原则是,只要有可执行进程,那么就总会有进程执行。但是只要系统中可运行的进程数目比处理器个数多,就注定某一给定时刻会有一些进程不能执行。4.1 多任务linux提供了抢占式的多任务处理模式,由调度程序来决定什么时候停止一个进程的运行,以便其他进程能够得到执行的机会。这个强制的挂起动作就叫做抢占。进程在被抢占之前能够运行的时间都是预先设置好的,叫进程的时间片。在非抢占模式下,除非进程自己主动停止运行,否则他会一直执行。4.2 linux的进程调度4.3 策略4.3.1 I/O消耗型和处理
阅读全文
摘要:3.1 进程 进程就是处于执行期的程序。但进程并不仅仅局限于一个可执行程序代码。通常进程还包括其他资源。进程就是正在执行的程序代码的实时结果。 执行线程,简称线程,是在进程活动中的对象。每个线程都拥有一个独立的程序计数器、进程栈和一组进程寄存器。内核调度的对象是线程而不是进程。进程提供两种虚拟机制:虚拟处理器和虚拟内存。虚拟处理器给进程一种假象,让这些进程觉得自己在独享处理器。虚拟内存让进程在分配和管理内存时觉得自己拥有整个系统的所有内存资源。同一个进程中的线程可以共享虚拟内存,但是每个都拥有各自的虚拟处理器。Linux系统中,通常是调用fork(),复制一个现有的进程来创建一个全新的进程..
阅读全文
摘要:1、何处安装并触及源码 内核源码一般安装在/usr/src/linux目录下。不要把这个源码树用于开发,因为编译你的c库所用的内核版本就链接到这棵树。不要以root的身份对内核进行修改,而应当是建立自己的主目录,仅以root身份安装新内核。即使在安装新内核时,/usr/src/linux目录都应当原封不动。2.1.3 使用补丁 patch -pl <../patch-x.y.z2.2 内核源码树2.3 编译内核2.3.1 配置内核1、make config 2、make gconfig3、make dconfig4、make oldconfig2.3.2 减少编译的垃圾信息make &g
阅读全文
摘要:1.3内核简介 内核的组成:1、中断服务程序——负责响应中断 2、调度程序——管理多个进程从而分享处理器时间 3、内存管理程序——管理进程地址空间 4、网络、进程间通信等系统服务程序 内核空间:内核独立于普通应用程序,一般处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限,这种系统态和被保护的内存空间,统称为内核空间。 用户空间:只能看到允许使用的部分系统资源,只能使用某些特定的系统功能,不能直接访问硬件,也不能访问内核划给别人的内存范围。 内核态与用户态:当内核运行的时候系统以内核态进入内核空间执行,执行普通用户程序时,系统以用户态...
阅读全文