第一章、绪论

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零碎与每个过程的一些信赖相干,信赖状把过程与一个特定的用户或用户组捆绑在一起。

信赖状在多用户零碎上尤为重要,因为信赖状能够决定每个过程能做什么,不能做什么,这样既保证了每个用户集体数据的完整性
也保障了零碎整体上的稳定性。
a.过程的能力:一种能力仅仅是一个标记,它表明是否容许过程执行一个特定的操作或一组特定的操作。

4.库:所有的全局内部符号名的线性地址。这些地址的调配或解析是由连贯程序实现的,链接程序把程序所有的指标文件收集起来并结构可执行文件。

5.动态库/共享库

动静库的优缺点:过程不须要拷贝指标代码、仅仅执行一个内存映射,把库文件的相干局部映射到过程的地址空间中。
毛病也很显著,动静的启动工夫较长,移植性也不如静链接的好,零碎中所蕴含的库版本发生变化时,
动静库连贯的程序可能不适宜本地运行。
动态库的优缺点:占用大量的磁盘空间。每个动态连贯的可执行文件都复制库代码的一部分。 gcc编译器提供-static选项通知链接程序应用动态库。

6.程序段和过程的线性区:
逻辑上,Unix程序的线性地址空间传统上被划分为几个叫段(segment)的区间:
a.注释段:蕴含可执行代码。
b.数据段:蕴含初始化的数据,也就是说,初始值寄存在可执行文件中的所有动态变量和全局变量(因为程序在启动时必须晓得它们的值)
c.bss段:蕴含未初始化的数据,也就是说,初值没有寄存在可执行文件中的所有全局变量(因为程序在援用它们之前才赋值)
d.堆栈段:蕴含程序的堆栈,堆栈中有返回地址、参数和被执行函数的局部变量。

堆:线性区蕴含动态分配给过程的内存区。
/sbin/init程序,它创立和监督在操作系统外层实现的所有过程的流动。init过程对应的线性区能够从(/proc/1/maps)文件失去这样的信息。

7.执行跟踪(execution tracing):是一个程序监督另一个程序执行的一种技术。被跟踪的程序一步一步地执行,直到承受到一个信号或调用一个零碎调用。

执行跟踪由调试程序(debugger)广泛应用,当然还应用其余技术(包含在被调试程序中插入断点及运行时拜访它的变量)。

8.ptrace()零碎调用过程执行跟踪。设置了CAP_SYS_PTRACE能力的过程能够跟踪零碎中的任何过程(除了init)。

相同,没有CAP_SYS_PTRACE能力的过程P只能跟踪
与P有雷同属主的过程。此外,两个过程不能同时跟踪一个过程。
a.ptrace()零碎调用批改被跟踪过程描述符的p_pptr域以使它指向跟踪过程,因而,跟踪过程变为被跟踪过程的无效父过程
跟踪完结时,以PTRAC_DETACH命令调用ptrace()时,这个零碎调用把p_pptr设置为p_oppter的值,复原被跟踪过程原来的父过程。
b.被跟踪过程相干的几个监控事件为:
一条独自汇编指令执行的完结
进入一个零碎调用
从一个零碎调用退出
接管到一个信号
c.当一个监控的事件产生时,被跟踪的程序进行,并将SIGCHID信号发送给它的父过程。当父过程心愿复原子过程的执行时,
就是用PTRACE_CONT、PTRACE_SINGLESTEP和
PTRACE_SYSCALL命令中的一条,这取决于父过程要监控那种事件。

9.可执行格局:Linux正式的可执行格局是ELF(Execuable and Linking Format)。

类型为linux_binfmt的对象所形容的可执行格局本质上提供以下三种办法:
a.loadbinary:通读寄存在可执行文件中的信息为以后过程建设一个新的执行环境。
b.load_shlib:用于动静地把一个共享库捆绑到一个曾经在运行的过程,这个是由uselib()零碎调用激活的。
c.core_dump:在名为core的文件中寄存以后过程的执行上下文。这个文件通常是在过程接管到一个缺省操作为"dump"的信号时被创立的
其格局取决于被执行程序的可执行类型。

linux_binfmt对象:处于一个简略的连贯链表中,第一个元素的地址被寄存在formats变量中。
能够通过调用register_binfmt()和unregister_binfmt()函数
在链表中插入和删除元素。

formats链表中的最初一个元素:是一个对解释脚本(interpreted script)的可执行格局进行形容的一个对象。定义了load_binary()办法。
其相应的do_load_script()
可执行文件是否是以两个#!开始,如果是,这个函数就以另一个可执行文件的门路作为参数解释第一行的其余部分,
并把文件名作为参数传递过来以执行这个脚本文件。

Linux容许用户注册本人定义的可执行格局:用如下的格局项/proc/sys/fs/binfmt_misc/register文件写入一个字符串
:name:type:offset:stringinterpreter:
name:新格局的标识符
type:辨认类型(M示意魔数,E示意扩大)
offse:魔数在文件中的起始偏移量
string:或者以魔数,或者以扩展名匹配的字节序列
mask:屏蔽string中的一些位的字符串
interpreter:程序解释器的残缺路径名

可执行文件的前128字节填充linux_binprm构造的buf域。
exec类函数:这些函数能用可执行文件所形容的新上下文代替过程的上下文。

总结

举荐一些好的视频网站:b 站、知乎、牛客网、极客工夫、51cto、腾讯课堂,网易云课程,基本上你所须要的视频材料都能够去找,切实不行上淘宝看看,我在b站也会日常更新,然而目前还不是很多。
哔哩哔哩
腾讯课堂
知乎
有趣味的敌人能够看看
我走的是 Linux C/C++ 路线,秋招投递这个岗位也很多,对于简历,面试方面感觉不好有余能够分割我,给你肯定的领导吧,这个看工夫。

对于想走 Linux C/C++ 方向的同学,基本上依照下面的路线走,多实战操作。