Linux内核完整架构

  1. 前言
    本文是“Linux内核分析”系列文章的第一篇,会以内核的核心功能为出发点,描述Linux内核的整体架构,以及架构之下主要的软件子系统。之后,会介绍Linux内核源文件的目录结构,并和各个软件子系统对应。

注:本文和其它的“Linux内核分析”文章都基于如下约定:
a) 内核版本为Linux 3.10.29(该版本是一个long term的版本,会被Linux社区持续维护至少2年),可以从下面的链接获取:https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.10.29.tar.xz
b) 鉴于嵌入式系统大多使用ARM处理器,因此涉及到体系结构部分的内容,都以ARM为分析对象

  1. Linux内核的核心功能
    如下图所示,Linux内核只是Linux操作系统一部分。对下,它管理系统的所有硬件设备;对上,它通过系统调用,向Library Routine(例如C库)或者其它应用程序提供接口。

因此,其核心功能就是:管理硬件设备,供应用程序使用。而现代计算机(无论是PC还是嵌入式系统)的标准组成,就是CPU、Memory(内存和外存)、输入输出设备、网络设备和其它的外围设备。所以为了管理这些设备,Linux内核提出了如下的架构。

  1. Linux内核的整体架构
    3.1 整体架构和子系统划分

上图说明了Linux内核的整体架构。根据内核的核心功能,Linux内核提出了5个子系统,分别负责如下的功能:

  1. Process Scheduler,也称作进程管理、进程调度。负责管理CPU资源,以便让各个进程可以以尽量公平的方式访问CPU。

  2. Memory Manager,内存管理。负责管理Memory(内存)资源,以便让各个进程可以安全地共享机器的内存资源。另外,内存管理会提供虚拟内存的机制,该机制可以让进程使用多于系统可用Memory的内存,不用的内存会通过文件系统保存在外部非易失存储器中,需要使用的时候,再取回到内存中。

  3. VFS(Virtual File System),虚拟文件系统。Linux内核将不同功能的外部设备,例如Disk设备(硬盘、磁盘、NAND Flash、Nor Flash等)、输入输出设备、显示设备等等,抽象为可以通过统一的文件操作接口(open、close、read、write等)来访问。这就是Linux系统“一切皆是文件”的体现(其实Linux做的并不彻底,因为CPU、内存、网络等还不是文件,如果真的需要一切皆是文件,还得看贝尔实验室正在开发的"Plan 9”的)。

  4. Network,网络子系统。负责管理系统的网络设备,并实现多种多样的网络标准。

  5. IPC(Inter-Process Communication),进程间通信。IPC不管理任何的硬件,它主要负责Linux系统中进程之间的通信。

3.2 进程调度(Process Scheduler)
进程调度是Linux内核中最重要的子系统,它主要提供对CPU的访问控制。因为在计算机中,CPU资源是有限的,而众多的应用程序都要使用CPU资源,所以需要“进程调度子系统”对CPU进行调度管理。

进程调度子系统包括4个子模块(见下图),它们的功能如下:

  1. Scheduling Policy,实现进程调度的策略,它决定哪个(或哪几个)进程将拥有CPU。

  2. Architecture-specific Schedulers,体系结构相关的部分,用于将对不同CPU的控制,抽象为统一的接口。这些控制主要在suspend和resume进程时使用,牵涉到CPU的寄存器访问、汇编指令操作等。

  3. Architecture-independent Scheduler,体系结构无关的部分。它会和“Scheduling Policy模块”沟通,决定接下来要执行哪个进程,然后通过“Architecture-specific Schedulers模块”resume指定的进程。

  4. System Call Interface,系统调用接口。进程调度子系统通过系统调用接口,将需要提供给用户空间的接口开放出去,同时屏蔽掉不需要用户空间程序关心的细节。

3.3 内存管理(Memory Manager, MM)
内存管理同样是Linux内核中最重要的子系统,它主要提供对内存资源的访问控制。Linux系统会在硬件物理内存和进程所使用的内存(称作虚拟内存)之间建立一种映射关系,这种映射是以进程为单位,因而不同的进程可以使用相同的虚拟内存,而这些相同的虚拟内存,可以映射到不同的物理内存上。

内存管理子系统包括3个子模块(见下图),它们的功能如下:

  1. Architecture Specific Managers,体系结构相关部分。提供用于访问硬件Memory的虚拟接口。

  2. Architecture Independent Manager,体系结构无关部分。提供所有的内存管理机制,包括:以进程为单位的memory mapping;虚拟内存的Swapping。

  3. System Call Interface,系统调用接口。通过该接口,向用户空间程序应用程序提供内存的分配、释放,文件的map等功能。

3.4 虚拟文件系统(Virtual Filesystem, VFS)
传统意义上的文件系统,是一种存储和组织计算机数据的方法。它用易懂、人性化的方法(文件和目录结构),抽象计算机磁盘、硬盘等设备上冰冷的数据块,从而使对它们的查找和访问变得容易。因而文件系统的实质,就是“存储和组织数据的方法”,文件系统的表现形式,就是“从某个设备中读取数据和向某个设备写入数据”。

随着计算机技术的进步,存储和组织数据的方法也是在不断进步的,从而导致有多种类型的文件系统,例如FAT、FAT32、NTFS、EXT2、EXT3等等。而为了兼容,操作系统或者内核,要以相同的表现形式,同时支持多种类型的文件系统,这就延伸出了虚拟文件系统(VFS)的概念。VFS的功能就是管理各种各样的文件系统,屏蔽它们的差异,以统一的方式,为用户程序提供访问文件的接口。

我们可以从磁盘、硬盘、NAND Flash等设备中读取或写入数据,因而最初的文件系统都是构建在这些设备之上的。这个概念也可以推广到其它的硬件设备,例如内存、显示器(LCD)、键盘、串口等等。我们对硬件设备的访问控制,也可以归纳为读取或者写入数据,因而可以用统一的文件操作接口访问。Linux内核就是这样做的,除了传统的磁盘文件系统之外,它还抽象出了设备文件系统、内存文件系统等等。这些逻辑,都是由VFS子系统实现。

VFS子系统包括6个子模块(见下图),它们的功能如下:

  1. Device Drivers,设备驱动,用于控制所有的外部设备及控制器。由于存在大量不能相互兼容的硬件设备(特别是嵌入式产品),所以也有非常多的设备驱动。因此,Linux内核中将近一半的Source Code都是设备驱动,大多数的Linux底层工程师(特别是国内的企业)都是在编写或者维护设备驱动,而无暇估计其它内容(它们恰恰是Linux内核的精髓所在)。

  2. Device Independent Interface, 该模块定义了描述硬件设备的统一方式(统一设备模型),所有的设备驱动都遵守这个定义,可以降低开发的难度。同时可以用一致的形势向上提供接口。

  3. Logical Systems,每一种文件系统,都会对应一个Logical System(逻辑文件系统),它会实现具体的文件系统逻辑。

  4. System Independent Interface,该模块负责以统一的接口(快设备和字符设备)表示硬件设备和逻辑文件系统,这样上层软件就不再关心具体的硬件形态了。

  5. System Call Interface,系统调用接口,向用户空间提供访问文件系统和硬件设备的统一的接口。

3.5 网络子系统(Net)
网络子系统在Linux内核中主要负责管理各种网络设备,并实现各种网络协议栈,最终实现通过网络连接其它系统的功能。在Linux内核中,网络子系统几乎是自成体系,它包括5个子模块(见下图),它们的功能如下:

  1. Network Device Drivers,网络设备的驱动,和VFS子系统中的设备驱动是一样的。

  2. Device Independent Interface,和VFS子系统中的是一样的。

  3. Network Protocols,实现各种网络传输协议,例如IP, TCP, UDP等等。

  4. Protocol Independent Interface,屏蔽不同的硬件设备和网络协议,以相同的格式提供接口(socket)。

  5. System Call interface,系统调用接口,向用户空间提供访问网络设备的统一的接口。

至于IPC子系统,由于功能比较单纯,这里就不再描述了。

  1. Linux内核源代码的目录结构
    Linux内核源代码包括三个主要部分:

  2. 内核核心代码,包括第3章所描述的各个子系统和子模块,以及其它的支撑子系统,例如电源管理、Linux初始化等

  3. 其它非核心代码,例如库文件(因为Linux内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等

  4. 编译脚本、配置文件、帮助文档、版权说明等辅助性文件

下图示使用ls命令看到的内核源代码的顶层目录结构,具体描述如下。

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 ---- 帮助、说明文档。

  1. 附录
    5.1 参考资料
    第3章各个子系统的架构图,拷贝自如下的网页:
    http://oss.org.cn/ossdocs/linux/kernel/a1/index.html

第一章、绪论
1.Unix文件可以是下列类型之一:
a.正规文件(regular file)
b.目录(directroy)
c.符号链(symbolic link)
d.块设备文件(block-oriented device file)
e.字符设备文件(charactor-oriented device file)
f.管道(pipe)命名管道(named pipe)(即FIFO)
h.套接字(socket)

2.内核分配给进程的虚拟地址空间由以下内存区域组成:
	a.程序的可执行代码
	b.程序的初始化数据
	c.程序的未初始化数据
	d.初始程序栈(即用户态栈)
	e.需要共享的库的可执行代码和数据
	f.堆(由程序动态请求的内存)

3.设备驱动程序
	内核通过设备驱动程序(device driver)与I/O设备打交道。设备驱动程序包含在内核中,由控制一个或多个设备的数据结构和函数组成。
	这些设备包括硬盘、键盘、鼠标和监视器等。通过特定的接口,每个驱动程序与内核中的其余部分(甚至与其他驱动程序)相互作用:
	优点:
		1.可以把特定设备的代码封装在特定的模块中。
		2.厂商可以不懂内核代码,只知道接口规范,就能增加新的设备。
		3.内核以统一的方式对待所有的设备,并且通过相同的接口访问这些设备。
		4.可以把设备驱动程序写成模块,并动态装到内核中,不需要重启系统,不需要的时候可以卸载模块,
			以减少存储在RAM中的内核映像大小。

第三章、进程
1.进程状态:
a.可运行状态
b.可中断状态
c.不可中断的等待状态
d.暂停状态
e.僵死状态

第十章、进程调度
1.涉及进程调度
a.传统上把进程分类:
I/O范围(I/O-bound):频繁地使用I/O设备,并花费很多时间等待I/O操作的完成。
CPU范围(CPU-bound):需要大量CPU时间的数值计算应用程序。

	b.非传统分类:
		交互式进程:如命令shell、文本编辑程序及图像应用程序。
		批处理进程:如编译程序、数据库搜索引擎及科学计算。
		实时进程:视频和音频应用程序、机器人控制程序及从物理传感器上收集数据的程序。

第十一章、内核同步
1.内核同步,内核态进程的非抢占性:
a.在内核态中运行的进程不会被其他进程取代,除非这个进程主动放弃CPU的控制权
b.中断或异常处理可以中断在内核态中运行的进程。但是,在中断处理程序结束时,该进程的内核控制路径被恢复
c.执行中断或异常处理的内核控制路径只能被执行中断或异常处理的其他内核控制路径所中断

2.SMP原子操作 从Intel 80286开始引入lock指令解决这中问题。
	lock只是一个用于一条汇编指令之前的特殊字节。当控制单元检测到一个lock字节时,就锁定内存总线
	这样其他处理器就不能存取下一条汇编语言指令的目的操作数所指定的内存单元。只有在这条指令执行完成时总线锁才会被释放。
	因此,带有lock前缀的读-修改-写指令即使在多处理器环境中也是原子的。
		
3.内核数据结构进行同步访问的常用方法是使用信号量和自旋锁。

第十二章、虚拟文件系统
1.通用文件模型由下列对象类型组成:
a.超级块对象(superblock object):存放已安装文件系统的有关信息。对于基于磁盘的文件系统,
这类对象通常对应于存放在磁盘上的文件系统控制块(filesystem control block)。
b.索引节点对象(inode object):存放关于具体文件的一般信息。对于基于磁盘的文件系统,
这类对象通常对应于存放在磁盘上的文件控制块(file control block)。
每个索引节点对象都有一个索引节点号,这个号唯一地标识文件系统中的指定文件。
c.文件对象(file object):存放打开文件与进程之间交互的相关信息。这类信息仅当进程访问文件期间存在于内核内存中。
d.目录项对象(dentry object):存放目录项与对应文件进行连接的信息。每个基于磁盘的文件系统都以自己特有的方式将该类信息存在磁盘上。
slab分配高速缓存中。
e.进程->文件对象->目录项对象->索引节点->(超级块对象)->磁盘文件。

2.虚拟文件系统,目录项对象属于以下四种状态之一:
	a.空闲状态:		还没有被VFS使用,对于德内存区由slab分配器进行管理。
	b.未使用状态:		该目录项对象当前还没有被内核使用。该对象的引用计数器d_count为NULL。
		但其d_indoe域只想相关索引节点。为了必要时回收内存,目录项包含有效信息,它的内存可能被丢失。
	c.正在使用状态:	该对象被内核使用。d_count的值为正数。目录项包含有效的信息,并且不能被丢弃。
	d.负状态:			与目录项相关的索引节点不复存在,那是因为相应的磁盘索引节点已被删除,d_count域被置NULL。

第十三章、管理I/O设备
1.三类内存地址:
a.逻辑地址(CPU内部使用)
b.线性地址(CPU内部使用)
c.物理地址(CPU从物理上驱动数据总线所用的内存地址)
d.总线地址(bus address):除CPU之外的硬件设备驱动数据总线所用的内存地址。

2.设备文件(mknod()系统调用来创建设备文件):用来表示Linux所支持的大部分I/O设备的,除了文件名,每个设备文件都还有三个主要属性。
	a.类型(type):块设备或字符设备
	b.主号(major number):从1到255之间的一个数,用以标识设备的类型,通常,具有相同主号和相同类型的所有设备文件共享相同的文件操作集合。
		因为他们是由同一设备驱动程序处理的。
	c.次号(minor number):在一组主号相同的设备之间唯一标识特定设备所使用的一个数字。

3.没有对应设备文件的I/O设备
	比如网卡:网卡把向外发送的数据放入通往远程计算机系统的一条线上,把从远程系统中接受到的报文装入内核内存。
			 由于没有使用文件系统,所以系统管理员必须建立设备名和网络地址之间的联系。
			 应用程序和网络接口之间的数据通信不是基于标准的有关文件的系统调用。
                             而是基于socket()、bind()、listen()、accept()和connect()系统调用。
			 这些系统调用对网络地址进行操作。这组系统调用由Unix BSD中首先引入,现在已经成为网络设备的标准变成模型。
			 
4.VFS对设备文件的处理:设备文件也在系统的目录数中。但它们和正规文件及目录有根本的不同。当进程访问正规文件时,
       它会通过文件系统访问磁盘分区的一些
	数据块;而在进程访问设备文件时,它只要驱动硬件设备就可以了。VFS的责任是为应用程序隐藏设备文件与正规文件之间的差异。
	VFS改变打开的设备文件的缺省文件操作。可以把对设备文件的任一系统调用转换成对设备相关的函数的调用,而不是对主文件系统对于函数的调用。
	设备相关的函数对硬件设备进行操作以完成进程所请求的操作。
	
	驱动程序:控制I/O设备的一组相关的函数称为设备驱动程序(device driver)。由于每个设备都有一个唯一的I/O控制器,因此也就有唯一的
			 命令和唯一的状态信息,所以大部分I/O设备类型都有自己的驱动程序。

5.设备文件调用open()函数执行的操作:
	a.如果设备驱动程序被包含在一个内核模块中,那么把引用计数器的值加1,以便只有把设备文件关闭之后才能卸载这个模块。
	b.如果设备驱动程序要处理多个同类型的设备,那么就是用次号来选择合适的驱动程序,如果需要,还要使用专门的文件操作表选择驱动程序。
	c.检查该设备是否真正存在,现在是否正在工作。
	d.如果必要,向硬件设备发送一个初始化命令序列。
	e.初始化设备驱动程序的数据结构。
			 
6.内核支持的级别
	a.根本不支持:应用程序使用设当的in和out汇编语言指令直接与设备的I/O端口进行交互。
	b.最小支持:内核不能设别硬件设备,但能识别I/O接口。用户程序把I/O接口是为能够读写字符流的顺序设备。
	c.扩展支持:内核设备硬件设备,并处理I/O设备本身,事实上,这种设备可能就没有对应的设备文件。

7.访问I/O设备的地址,可以从/proc/ioports文件中获得。

8.内核对于块设备的支持特点:
	a.通过VFS提供统一接口
	b.对磁盘数据进行有效的链接
	c.为数据提供磁盘高速缓存
	
9.内核基本上把I/O数据传送划分成两类:
	a.缓冲区I/O操作:所传送的数据保存在缓冲区中,缓冲区是磁盘数据在内核中的普通内存容器。每个缓冲区都和一个特定的块相关联
	  而这个块由一个设备号和一个块号来标识
	b.页I/O操作:所传输的数据保存在页框中,每个页框包含的数据都属于正规文件。因为没有必要把这种数据存放在相邻的磁盘中。
	  所以就是用文件的索引节点和文件内的偏移量来标识这种数据。主要用于读取正规文件、文件内存映射和交换。
	  
10.所谓块(block):就是块设备驱动程序在一次单独操作中所传送的一大块相邻字节。
   扇区(sector):扇区是硬件设备传送数据的基本单元。
   
11.块设备驱动程序的两部分:
	a.高级驱动程序:处理VFS层。
	b.低级驱动程序:处理硬件设备。

第十五章、访问正规文件
1.从正规文件读取数据:generic_file_read()函数实现了大部分文件系统的正规文件的read方法。
2.对正规文件进行预读:正规文件的预读需要的算法比物理块的预读需要的算法更复杂:
a.由于数据是逐页进行读取的,因此预读算法不必考虑页内偏移量,只考虑所访问的页在文件内部的位置就可以了。
b.当前访问与上一次访问不是顺序的时,预读就必须从头开始重新执行。
c.当进程一直反复地访问同一页时(该文件只有很少的一部分被使用),应该减慢预读的速度甚至停止执行。
d.如果需要,预读算法必须激活低级I/O设备驱动程序来确保新页会被读取。
e.内核通过多次调用一个名为:try_to_read_ahead()的函数来执行预读操作(read ahead operation),一次预读一页。
f.对于每个请求页,内核都要调用generic_file_readhead()函数,该函数确定是否要执行预读操作。

3.写正规文件:write()系统调用会涉及把数据从调用进程的用户态地址空间中移动到内核数据结构中,然后再移动到磁盘上。
			 文件对象的write方法允许每种文件类型都定义一个专用的写操作。
	a.写操作发生时,有效数据是在缓冲区高速缓存中,而不是在页高速缓存中,更确切地说,当write方法修改了文件的任何部分时。
	  与这些部分对应的页高速缓存中的所有页都不再包含有效数据。一个进程可能认为自己在读取正确数据,
             但是却没看到其他进程对这些数据所做的修改。
	b.所有基于磁盘的文件系统的write方法都要调用update_vm_cache()函数来修改读操作所使用的页高速缓存。
	c.通过页高速缓存对正规文件执行的写操作,只能用于网络文件系统。文件的write方法是使用generic_file_write()函数实现。
	
4.内存映射:一个线性区可以和基于磁盘的文件系统中的一个文件(或者文件的一部分)相关联。这就是说,内核会把线性区中对一个页中字节的访问转换成
		   对正规文件中相对于字节的操作,这种技术成为内存映射。
	a.共享的:对线性区中的任何写操作都会修改磁盘上的文件。而且,如果进程对共享内存映射中的一个页进行写,
               那么这种修改对于其他映射了相同文件的所有
			进程来说都是可见的。
	b.私有的:当进程创建的映射只是为读文件,而不是写文件时才会使用。处于这种目的,私有映射的效率要比共享映射的效率更高。
	    但是私有映射页的认识写操作都会使内核不再映射该文件中的页。一个写操作即不会改磁盘上的文件,
                对访问相同文件的其他进程来说这种改变也是不可见的。
	c.使用mmap()系统调用创建一个新的内存映射。必须指定MAP_SHARED或MAP_PRIVATE标志。

第十六章、磁盘数据结构
1.任何Ext2分区中的第一个块从不受Ext2文件系统的管理,因为这一块是为启动扇区所保留的。Ext2分区的其余部分被分成块组(block group)。
2.块组中的每个块包含下列信息之一:
a.一个Ext2文件系统超级块的拷贝
b.一组块组描述符的拷贝
c.一个数据块位图:标识在一组中块的使用和空闲状况。
d.一个索引节点位图
e.一组索引节点
f.属于文件的一块数据;即一个数据块。
3.如果一个块中不包含任何有意义的信息,就说这个块是空的。
4.在Ext2文件系统中的所有块组大小相同并被顺序存放,因此,内核可以从块组的整数索引很容易地得到磁盘中一个块组的位置。
5.超级块与组描述符被复制到每个块组中。只有块组0中所包含的超级块和描述符才由内核使用,而其余的超级块和组描述符保持不变
事实上,内核甚至不考虑它们。
6./sbin/e2fsck程序对Ext2文件系统的状态执行一致性检查时,就引用存放在块组0中的超级块和组描述符,然后把它们拷贝到其他所有的块组中。
7.每组之多有8 x b块,b是以字节单位的块大小。
8.示例:
8GB的Ext2分区
块的大小为4KB
块位图的大小4KB(b=4KB)
最多描述32KB的数据块
每个块组的容量:4KB x 32KB = 128MB
最多需要的块组数: n = 8GB/128MB = 64
9.磁盘数据结构:
a.超级块的域:
索引节点的总数
以块位单位的文件系统的大小
保留的块数
空闲块计数器
空闲索引节点计数器
第一次使用的块号(总为1)
块的大小
片的大小
每组中的块数
每组中的片数

b.组描述符:每个块组有自己的组描述符,为ext2_group_desc结构。
Ext2组描述符的域
块位图的块号
索引节点位图的块号
第一个索引节点表块的块号
组中空闲块的个数
组中索引节点的个数
组中目录的个数

c.位图:是位的序列,0表示相应的索引节点块或数据块是空闲的,1表示占用。
d.索引节点表:所有索引节点的大小相同,即128字节。索引节点表第一个块的块号存放在组描述符的bg_inode_table域中。
Ext2磁盘索引节点的域:
文件类型和访问权限
拥有者的标识符
以字节为单位的文件长度
最后一次文件访问的时间

文件的索引节点号没有必要再磁盘上存放,因为它的值可以从块组号和它在索引节点表中的相对于位置而得出。
10.Ext2的文件操作:
VFS方法的read和mmap是由很多文件系统共用的通用函数实现的。这些方法存放在
ext2_file_operations表中:
lseek -> ext2_file_lseek()
read -> generic_file_read()
write -> ext2_file_write()

11.各种文件类型如何使用磁盘块
	正规文件:正规文件只有在开始有数据时才需要数据块。
	目录:Ext2以一种特殊的文件实现了目录,这种文件的数据块存放了文件名和相应的所有节点号。
		 数据块中包含了类型为ext2_dir_entry_2的结构
		 名字域最大为EXT2_NAME_LEN(通常是255)个字符的边长数组。
		 目录项的长度是4的倍数
	符号链:符号链的路径名达到60个字符,就把它存放在索引节点的i_blocks域,该域是由15个4字节整数组成的数组,因此无需数据块
		    如果路径名大于60个字符,就需要一个单独的数据块。
	设备文件、管道和套接字:这些类型的文件不需要数据块,所有必须的信息都存放在索引节点中。
	
12.Ext2文件的类型
	0 未知
	1 正规文件
	2 目录
	3 字符设备
	4 块设备
	5 命名管道
	6 套接字
	7 符号链
	
13.文件的洞是正规文件的一部分,它是一些空字符但没有存放在磁盘的任何数据块中。
    引入文件的洞是为了避免磁盘空间的浪费。它们被广泛地用在数据库引用中,更一般的说,用于文件上散列法的所有应用。

第十八章 进程通信
1.进程间通信的机制:
管道和FIFO(管道):最适合在进程之间实现生产者/消费者的交互。有些进程往管道中写入数据,而另外一些进程则从管道中读取数据。
无名管道:用户无法打开一个现有的管道。除非管道是由一个公共的祖先进程创建的。
有名管道:有磁盘索引节点,因此任何进程都可以访问FIFO,没有使用数据块,使用内核缓冲区。
信号量IPC(Interprocess Communicatoin),表示一组系统调用,这组系统调用
允许用户态进程:
a.通过信号量和其他进程进行同步
b.向其他进程发送消息或者从其他进程处接受消息
c.和其他进程共享一个线性区
使用IPC资源:
信号量:semget()
消息队列:msgget()
共享内存:shmget()

	消息:允许进程异步地交换信息(小块数据)。可以认为消息是传递附加信息的信号。
	共享内存:当进程之间在高效地共享大量数据时,这是一种最合适的交互方式。
	套接字(socket):涉及到网络相关。

第十九章、程序的执行
1.进程概念:在Unix中是用来表示正在运行的一组程序竞争系统资源的行为。
2.内核需要处理的问题(把一组指令装入内存并让CPU执行):
不同的可执行文件格式: Linux的一个著名之处就是能执行其他操作系统所编译的二进制文件。
共享库: 很多可执行文件并不包含运行程序所需要的所有代码,而是希望在运行时由内核从函数库装入函数。
执行上下文中的其他信息: 包括程序员熟悉的命令行参数与环境变量。

3.进程的信任状和能力:Unix系统与每个进程

————————————————
版权声明:本文为CSDN博主「我在爱的国」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/magaiou/article/details/80322133

你可能感兴趣的:(Linux内核完整架构)