您好,欢迎来到划驼旅游。
搜索
您的当前位置:首页2012年Linux期末总结(多人多次修补版)

2012年Linux期末总结(多人多次修补版)

来源:划驼旅游


下面总结针对老师上课时勾画的重点,仅供参考。时间有限,总结的比较仓促,大家发现有什么错误或者有需要补充的可以Q我,或者在群里给出补充和修改内容。大家应该以书本为主。第1,2章 内核简介和从内核出发• linux内核与windows内核差异

答:操作系统内核可以分为两大阵营:单内核和微内核(第三阵营是外内核,主要用在科研系统中,不做讨论)

单内核:把内核从整体上作为一个单独的大过程来实现,同时也运行在一个单独的地址空间。通常以单个静态二进制文件存于磁盘,具有简单和性能高的特点。

微内核:微内核并不作为一个单独的大过程来实现,相反,微内核的功能被划分成多个的过程,每个过程叫做一个服务器;通过消息传递处理微内核的通信。(详细见中文版6页)

Linux是单内核,windows是微内核。差异分析大家自己看着办,从6页自己选择性填写。

• 内核版本表示,各个位置上数的代表含义答:linux内核有两种:稳定和处于开发中的。

上图中:第一个数字是版本号,第二个数字是从版本号,第三个数字是修订版本号,第四个数字可选,表示稳定的版本号。从第二个数字的奇偶性可以判别该内核是稳定版还是开发版,奇数表示开发版,偶数表示稳定版。6表示是稳定版,而该稳定版本号是1.

• 内核编译,编译完成后生成的镜像文件名称

答:linux实验课不止一次用到内核编译,在这我简单说明下:先到官网下载一个linux版本的源代码,tar 命令解压,如tar xvjf linux-x.y.z.bz2.各参数含义:-x:解压,-v:显示所有过程,-j:有bz2属性的,-f:使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名。解压后进入相应解压文件目录,进行编译前的相关配置及清理工作。使用一种内核编译方法,其中自动精简内核编译配置make localmodconfig适合于新手。开始编译 sudo make-kpkg clean ;make-kpkg --initrd --append-to-version=-xxx kernel_image。-xxx是自己取得一个名字。编译完成,cd ..退到上以及目录执行sudo dpkg -i linux-image-2.6.34.11-xxx_i386.deb(镜像文件名称) ,安装生成的镜像文件。之后的配置grub开机启动项在此不赘述,有兴趣自行了解

Linux期末总结

(主要有两个参数,default:决定grub引导时光标默认停留的引导标签位置,timeout:停留在引导标签页的时间)

(不知道考试是根据书本的步骤,还是上述的步骤,大家考虑考虑吧...书本P12页)

• Linux是单内核,内核运行在单独的内核空间地址上。我当时记到的是执行时,内核全部载入。不过觉得有问题,书上说的是linux汲取微内核精华,支持动态装载内核模块,允许在需要的时刻动态地卸除和加载部分内核代码,大家自己判断。

• 堆栈大小:用户空间和内核空间对应各自的栈,其中用户空间堆栈较大,且能动态增长。内核栈的准确大小随体系结构而变。在X86上,栈的大小在编译时配置。在32位机上,内核栈是2页,对应8KB;在位机上。内核栈也是2页,对应16KB。

第3章 进程管理

1. 每个进程对应的PCB及task-struct

内核把进程列表存放在叫做任务队列的双向循链表中,链表中的每一个项都是一个task-struct结构。Linux通过slab高速缓存层分配器分配task-struct结构,达到对象复用和缓存着色的目的。注意一下在内核栈中用struct thread_info结构来指向进程描述符,即指向struct task_struct 结构。每个任务的thread_info 结构在它的内核栈的尾端分配。结构中的task域中存放的是指向该任务实际task_struct的指针。

2.线程和进程的关系,fork(),clone()函数的用法及差别

进程就是处于执行期的程序,当然还要包含其他资源,如打开的文件,挂起的信号,内核内部数据,处理器状态,一个活多个具有内存映射的内存空间地址及一个或多个执行的线程,存放全局变量的数据段等等。

线程是进程中活动的对象,每个线程都有自己的程序计数器,进程栈和一组进程寄存器。内核调度的对象是线程而不是进程。Linux对进程和线程并不特别区分。Fork()函数创建进程,linux的fork()函数使用写时拷贝,子进程和父进程共享一份拷贝(子进程没有写入时)。调用fork()函数的是父进程,新产生的是子进程。在该调用结束时,在返回点的这个相同位置上,父进程恢复执行,子进程开始执行,即现在有两个进程在执行了,而且执行的是相同的一块代码,哪个获得处理器就执行。Fork()系统调用从内核返回两次,当进程pid为0时表示父进程子在运行,pid>0时表示子进程在运行,pid<0表示创建子进程失败。

对于clone()函数,首先看其参数标志:

看一个有关clone的函数:clone(CLONE_VM | CLONE_FS |CLONE_FILES | CLONE_SIGHAND, 0);

这个函数调用与fork()差不多。这里是线程创建,所以在调用clone()的时候需要传递一些参数标志来指明所需要共享的资源.

实际上fork()函数是通过调用clone()来实现的。只需传递相应的参数标志。

具体有关clone().fork()等进程线程创建函数说明可以看下中文版3.3,3.4节。

3.进程的5种状态

答:TASK_RUNNING(运行),TASK_INTERRUPTIBLE(可中断),TASK_UNINTERRUPTIBLE(不可中断),

_TASK_TRACED(追踪),_TASK_STOPPED(停止);具体每种状态的说明见中文版24页。

4. 写时拷贝

答:传统的fork()系统调用直接把所有的资源复制给新船将改建的进程,这种实现过于简单且效率低下,因为它拷贝的数据也许并不共享,而且更糟糕的是,新进程打算用一个新的映像,那之前的复制就全都浪费了。Linux的fork()使用写时拷贝,写实拷贝是一种可以推迟甚至免除拷贝数据的技术。内核一开始并不复制整个进程的地址空间。而是让父子进程共享一个拷贝。当子进程需要写入时,数据才被复制,这时子进程拥有了自己的拷贝。写时拷贝避免了拷贝大量根本就不会被使用的数据,当子进程没有数据写入时,fork()函数的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描述符。

*:内核线程与普通线程的区别:没有的地址空间,只在内核空间运行,只能由其他 内核线程创建。

第4章 进程调度*:调度器类:

linux调度器是以模块方式提供的,这样做的目的是允许不同类型的进程可以有针对性的选择调度算法,这种模块化结构被称为调度器类,它允许多种不同的可以动态添加的调度算法并存,调度属于自己范畴的进程。每个调度器都有一个优先级,基础调度器按照优先级顺序遍历调度器类。

1. 进程调度

答:首先说明一下进程的分类:I/O消耗型进程,处理器消耗型进程。进程的调度就是针对这两种不同类型的进程展开的。

A:前者指大部分时间用来提交I/O请求或是等待I/O请求,其经常处于可运行状态,但是 运行时间较短,在等待更多I/O请求时会被阻塞; B:后者把大部分时间用在执行代码上,除非被抢占,否则他们通常都一直不停的运行, 但从系统响应速度考虑,不应该让他经常运行,所以降低其调度频率,延长运行时 间。当然也不是绝对的,进程调度通常 要在两个矛盾的目标中寻求平衡:进程 的响应 时间和最大系统利用率。

2. 普通进程调度算法:完全公平调度算法(CFS)

用户空间的nice值范围(-20-19)值越小,优先级越高。CFS是一个针对普通进程的调度类,在linux中被称为SCHED_NORMAL。

CFS对时间片分配方式进行根本性的重新设计,即不再根据nice值的大小分配相应的时间片,而是依据nice值分配给进程一个处理器的使用比重。CFS允许每个进程运行一段时间,循环轮转,选择运行最少的进程作为下一个运行进程,CFS在所有可运行的进程总数基础上计算出一个进程应该运行多久,而不是依靠nice值来计算时间片。nice值在CFS中被作为进程获得的处理器运行比的权重:越高的nice值进程获得更低的处理器使用权重,这是相对默认nice值而言的;相反,更低的nice值的进程获得更高的处理器使用权重。(注意这里nice的相对值才影响处理器权重的分配,具体例子见书42页)

nice值对时间片的作用不再是算术加权,而是几何加权。任何nice值对应的绝对时间不再是一个绝对值,而是处理器的使用比。

3. 实时进程调度算法:提供一种软实时工作方式。

内核空间的优先级范围(0-MAX_RI_PRIO-1),MAX_RI_PRIO=100实时调度策略:对应的调度类是SCHED_FIFO(先进先出)和

SCHED_RR(它是带有时间片的SCHED_FIFO,即实时轮流调度算法)。

由于SCHED_NORMAL级的进程nice值共享了这个取值空间,所以它的取值范围是(MAX_RI_PRIO--MAX_RI_PRIO+40),即nice值从(-20-19)直接对应到(100-139)

*:软实时:内核调度进程,尽力使进程在它的限定时间到来之前运行,但内核不保证总能满足这些进程的要求。

*:硬实时系统:保证在一定条件下,可以满足任何调度的要求。第5章 系统调用

*:系统调用在用户空间进程和硬件设备之间添加的中间层的三个作用:

A:为用户空间提供了一种硬件的抽象接口。 B:保证了系统的稳定和安全。

C:因为每个进程都运行在虚拟系统中,所以在用户空间和系统的其余部分提供这样一层 公共接口。

*:定义系统调用函数的限定词‘asmlinkage'是一个编译指令,通知编译器仅从栈中提取该函数的参数。其返回值类型:用户(int)、内核(long)。

1. 系统调用过程

答:首先强调一点,在linux中,系统调用是用户空间访问内核的唯一手段;除异常与陷入外,它们是内核唯一的合法入口。

*系统调用的性能:Linux的系统调用比其他许多操作系统执行的要快。 A:Linux很短的上下文切换时间是一个重要的原因,进出内核被优化得简洁高效。

B:另外一个原因是系统调用处理程序和每一个系统调用本身也非常简洁。

系统调用层次结构:

用户程序------>C库(即API):INT 0x80 ----->system_call------->系统调用服务例程-------->内核程序

执行系统调用的连锁反应:陷入内核,传递系统调用号和参数,执行正确的系统调用函数,并把返回值带回用户空间。

宏调用:Linux提供一组宏,用于在用户空间对系统调用进行访问。形如_syscalln(),其中n的范围0到6,代表需要传递的系统调用参数个数,每个宏有2+2*n个参数。

另外补充:应用程序接口(API),要了解的看书57页;系统调用号,每个系统调用对应一个独一无二的系统调用号,一旦分配就不能再有任何改变否则编译好的应用程序就会崩溃。详细见书59页第6章 内核数据结构1. 内核中的数据结构

答:链表:链表是一种存放和操作可变数量(常称为节点)的数据结构 遍历的方法:使用list_for_each()宏。

队列:一种先进先出的数据结构(生产者消费者问题)。Linux通过队列实现kfifo,提供两个主要操作:enqueue(入队)和dequeue(出

队)。维护两个偏移量:入口偏移和出口偏移。

映射:也称为关联数组,实际上是一个由唯一键组合的集合,而每个键必然关联一个特定的值。

二叉树:主要了解自平衡二叉树,即一个所有叶子节点深度之差不超过1的二叉搜索树。(不明白的见书85)

*二叉搜索树(BST):是一个节点有序的二叉树,其顺序(小--大):左根右。

*平衡二叉搜索树:是一个所有节点深度差不超过1的二叉搜索树。 *自平衡二叉搜索树:是指其操作都试图维持(半)平衡的二叉搜索树。

*红黑树:是一种自平衡二叉搜索树,其具有特殊的着色属性,或红色或黑色。其保证了

最深的叶子节点的深度不会大于两倍的最浅叶子节点的深度,所以总是半平衡的。

其用途是实现关联数组。数据结构的适用范围:

• 如果你的数据集合的主要操作是遍历数据,或需要存储相对相对较少或大小不明的数据量时,就使用链表。

• 如果你的代码符合生产者/消费者模式,或需要一个定长缓冲,则使用队列。

• 如果你需要映射一个UID到一个对象,就使用映射。

• 如果你需要存储大量数据,并且迅速检索,那么红黑树最好(自平衡二叉树)

第7章 中断和中断处理

中断:本质是一种特殊的电信号,由硬件设备发向处理器;可以随时向处理器发出中断请 求。

异常:它在产生时必须考虑与处理器时钟同步,也称为同步中断。如:被0除、缺页,必须靠

内核来处理的时候,处理器就会产生一个异常。

中断处理程序:内核执行一个函数来响应一个特定的中断,该函数叫做中断处理程序或中断服务例程。中断处理程序运行在被我们称之为中断上下文的特殊上下文中。该上下文也被称作原子上下文,即该上下文中代码不可阻塞。必须保证中断处理程序能够快速执行。

• 中断分两部分:上半部和下半部,用来平衡快速执行和完成大量工作量之间的矛盾。中断处理程序是上半部分:接收到一个中

断,立即开始执行,但只做有严格时限的工作,如对接收的中断应答和硬件复位,这些工作在所用中断被禁止时完成,即关中断;下半部分在第8章中说明,开中断。(例子见书93页)

• 中断注册函数:(1).驱动程序通过request_irq()函数注册一个中断处理程序,并且激活给定的中断线,以处理中断。成功执行则返回0,此函数可能会睡眠,因此,不能在中断上下文或其他不允许阻塞的代码中调用该函数。(2).Free_irq()注销中断处理程序,禁用其中断线。说到这里,简单给出IRQ的定义:不同的设备对应的中断不同,通过一个唯一的数字标识。这些数字标识通常被称作中断请求线(IRQ),如IRQ 0是时钟中断,IRQ 1是键盘中断。一条中断请求线对应一种中断,可连接多个同种类型的硬件设备。

• 共享的中断处理程序与非共享的中断处理程序的差异:

答:a. request_irq()的参数flags必须设置IRQF_SHARED标志。

b.对于每个注册中断处理程序来说,dev参数必须唯一。

c. 中断处理程序必须能够区分它的设备是否真的产生了中断。共享的中断线的驱动程序都必须满足以上要求。

• 中断统计信息查看

答:两个宏,in_interrupt(),in_irq,说明见下表:也可参考书106页。

第8章 下半部和推后执行的工作

上半部分需要完成的任务在第7章中已经给出,不再赘述。上半部分局限:

A:中断处理程序以异步方式执行,有可能打断其他重要代码的执行;

B:如当前有一中断处理程序在执行,则同级的中断会被屏蔽,因此,要求其执 行的越快越好;

C:有很高的时限要求;

D:中断处理程序不在进程上下文中运行,所以它们不能阻塞。

下半部分:执行与中断处理密切相关但中断处理程序本身不执行的工作。

中断机制:分为三种,软中断(Softirqs),Tasklet,工作队列(Work queue

软中断:使用范围小,只在那些执行频率很高和连续性要求很高的情况下使 用。

Tasklet:是通过软中断实现的,所以它本身也是一种软中断。通常应该使用它。

*:tasklet_schedule()的执行步骤:

A.检查tasklet的状态是否为TASKLET_STATE_SCHED。如是,说明tasklet已

经被调度过了,函数立即返回。 B.调用_tasklet_schedule()。

C.保存中断状态,然后禁止本地中断。

D.把需要调度的tasklet加到每个处理器一个的tasklet_vec链表或

tasklet_hi_vec链表的表头上去。

E.唤起TASKLET_SOFTIRQ或HI_SOFTIRQ软中断。 F.恢复软中断到原状态并返回。适用范围:

• 如果被考察代码本身多线索化的工作做得非常好,如网络子系统,它完全使用单处理器变量,那么选择软中断。

• 如果代码的多线索化考虑的并不是很充分,那么选择tasklet好些。

• 如果需要把任务推后到进程上下文中完成,那么只能选择工作队列了。

区别:软中断和tasklet不允许休眠,而workqueue则可以。工作队列可以把工作推后,交由一个内核线程去执行。

第9章 内核同步介绍

首先扯一些相关的,在使用共享内存的应用程序中,程序员必须特别留意对共享资源的保护。于是就有了临界区的说法:访问和操作共享数据的代码段。为了在临界区中避免并发访问,我们必须保证这些代码原子执行,即相当于整个临界区是一个不可分割的指令一样。有两个或者两个以上的访问者同时来瓜分的话很容易出现错误。一旦上述情况发生,就称之为竞争条件。我们把避免并发和防止竞争条件称之为同步。

• 死锁(dead lock):产生条件:要有一个或者多个执行线程和一个或多个资源,每个线程都在等待其中的一个资源,但所

有的资源都已经被占用。所有线程都在相互等待,但它们永远都不会释放已经占有的资源。于是任何线程都无法继续,死锁发生。

简单的一个例子,线程A已经获得资源m,它还需要资源n才能完成,而此时线程B已经获得资源n,它需要获得资源m才能完成,这样A和B都希望获得对方的资源而又不肯释放自己已经获得的资源,所以两个线程就都不能完成,发生死锁。• 避免死锁的规则:• 按顺序加锁。• 防止发生饥饿。

• 不要重复请求同一个锁。

• 设计应力求简单-----越复杂的加锁方案越有可能造成死锁。

第10章 内核同步方法

• 原子操作(Atomic Operations):它是其他同步方法的基石。原子操作可以保证指令以原子的方式执行------执行过程不被打断。两组操作接口:针对整数和单独的位进行操作。原子操作通常是内联函数,往往是通过内嵌汇编指令来实现的。此种函数往往会被定义成一个宏。

• 自旋锁(spin lock):自旋锁最多只能被一个可执行的线程持有。如果一个线程企图得到一个已经被持有的自旋锁,那么该线程就会一直进行忙循环等待—等待锁重新可用。如果锁未被征用,则立即获得。说的简单些,一个被征用的自旋锁使得请求它的线程在等待锁重新可用时自旋,即忙等待。

自旋锁特征:不休眠(正确性有待考证),不可递归,可以使用在中断处理程序中,加锁前首先禁止本地中断,解锁后打开本地中断。

读写自旋锁:解决读者写者问题,优先照顾读者。解释:当读锁被持有时,写操作为了互斥访问只能等待,但是,读者确可以继续成功地获得锁。读者很多时,写者容易产生饥饿。

• 信号量(Semaphores):信号量是一种睡眠锁。如果一个任务试图获得一个已经被占用的信号量,信号量会将其推进一个等待队列,然后让其睡眠。

为了找到一种更加简单的睡眠锁,内核引入了互斥体

(metux),指任何可以睡眠的强制互斥锁,简单的说互斥体

是一种互斥信号。

• 自旋锁与信号量的比较

• 顺序锁(Sequential locks):通常被称为seq锁。这种锁提供一种简单机制,用于读写共享数据。实现这个锁主要依靠一个计数器。写操作会使序列值增加,而在读操作之前和之后都会去读取序号,如果前后相等,说明读操作未被打断,否则被打断。顺序锁优先照顾写者,即在没有其他写者的时候,写锁总是可以被一个写者获得,读者不影响写者。当有多个写者的时候,读者很可能饥饿。

• 顺序与屏障的概念与定义(Ordering and Barriers)

答:当处理多处理器之间或硬件设备之间的同步问题时,有时需要在你的程序代码中以指定的顺序发出读内存和写内存指令。在和硬件交互时,时常要确保一个给定的读操作发生在其他读操作或写操作之前。另外,在多处理器上,可能需要按写数据的顺序读数据(称之为RAW,即写后读相关)。编译器与处理器为了提高效率,会对读写操作重排序。所有可能重排序读和写操作的处理器提供了机器指令来确保顺序要求,即和顺序执行的效果等效。同样的,也可以指示编译器不要给定点周围的指令进行重新排序。这些确保顺寻的指令称之为屏障(barriers)

第12 章 内存管理

• Page表示

答:内核把物理页作为内存管理的基本单位。内存管理单元(MMU)通常以页为单位进行处理。大多数32为体系结构支持4KB的页,位体系结构支持8KB的页。页结构用struct page表示,有兴趣的同学可以在书上186页看下,书上给出了几个域的解释。

注意一点:page结构与物理页相关。

• 区(zone):区的使用和分布是与体系结构相关的。内核使用区对具有相似特性的页进行分租,形成内存池。Linux主要使用了四种分区:

• ZONE_DMA------这个分区包含的页能用来执行DMA操

作。(块数据读取)

• ZONE_DMA32------和ZONE_DMA类似,该区包含的页面可用来执行DMA操作,但这些页面只能被32位设备访问。• ZONE_NORMAL------这个区包含的都是能正常映射的页。

• ZONE_HIGHEM------这个区包含“高端内存”,其中的页并不能永久地映射到内核地址空间。

• 高速缓存层(slab)的作用

答:高速缓存分成多个slab;快速存储频繁使用的对象类型,便于数据频繁分配和回收;slab由一个或多个物理上连续的页组成;每一个slab处于三种状态之一:满、部分满、空。

• 使用CPU数据的原因

答:1. 减少了数据锁定。需要确保本地处理器只会访问它自己的数据。

2. 使用每个CPU数据可以大大减少缓存失效。(理想情况下只会访问自己的

数据,而不需要去操作其他处理器缓存中的数据,导致更新自己的缓

存,发生缓存失效)

• 内存空间分配,各分配函数的使用范围

Kmalloc():与用户空间malloc()类似,只是多了一个flags参数,kmalloc()函数是一个简单的接口,用它获得以字节为单位的一块内存。

Vmalloc():工作方式类似于kmalloc(),只是vmalloc()分配的内存虚拟地址是连续的,而kmalloc()分配的物理地址是连续的。Slab:高速缓存层用于数据频繁的分配和回收。详细设计见书198页。使用范围:

• 如果需要连续的物理页,则使用kmalloc().• 如果想从高端内存分配,使用alloc_pages().

• 如果不需要物理上连续的页,而仅仅需要虚拟地址连续的页,就使用vmalloc().

• 如果要创建和撤销很大的数据结构,那么考虑建立slab高速缓存,slab层会给每个处理器维持一个对象高速缓存(它

会极大的提高对象分配和回收的性能)。

下面强调一下在kmalloc()函数中最长用的两个标志:GFP_ATOMIC,GFP_KERNEL.

GFP_ATOMIC表示进行不睡眠的高优先级分配。对于可以睡眠的代码,则使用GFP_KERNEL获取所需的内存。

第13章 虚拟文件系统

• 四种文件对象

答:A. 超级块对象(superblock object):代表一个具体的已经安装的文件系

统。各种文件系统都必须实现之,通常对应于存放在磁盘特定扇区中的文

件系统超级块或文件系统控制块。

B. 索引节点对象(inode object):代表一个具体文件,由inode结构体表 示。

C. 目录项对象(dentry object):代表一个目录项,是路径的一个组成部 分。

D. 文件对象(file object): 代表由进程打开的文件,是已打开的文件在内存

中的表示,该对象由相应的open()系统调用创建,由close()系统调用

撤销。随进程的生灭而生灭。

简单说明:前两者一般保存在硬盘上。后两者在使用时才有,即这两种对象实际上没有对应的磁盘数据。四种类型对象之间关系图:

第15章 进程地址空间• 内存描述符

内核使用内存描述符结构表示进程的地址空间,该结构包含了和进程地址空间有关的全部信息。用mm_struct结构表示。

下图给出了mm_struct的详细内容。要是觉得不清楚可以去看书248页。讲的很清楚。最好记熟书上详细给出的该结构中某些域表示的含义。 2. mm_struct与内核线程

内核线程没有进程地址空间,也没有相关的内存描述符,因为内核线程并不需要访问任何用户空间的内存。为避免浪费内存,内核线程将使用前一个进程的内存描述符。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo6.com 版权所有 湘ICP备2023023988号-11

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务