操作系统linux内核.docx
- 文档编号:9616657
- 上传时间:2023-05-20
- 格式:DOCX
- 页数:9
- 大小:21.28KB
操作系统linux内核.docx
《操作系统linux内核.docx》由会员分享,可在线阅读,更多相关《操作系统linux内核.docx(9页珍藏版)》请在冰点文库上搜索。
操作系统linux内核
学号:
1049721101375
课程论文
课程名称
操作系统分析与设计
学院
计算机科学与技术学院
专业
计算机应用技术
班级
姓名
指导教师
2011—2012学年第1学期
Linux操作系统内核同步机制分析
摘要:
通过分析Linux内核2.4版本的源代码,讨论了Linux操作系统内核同步机制基本原理和Linux内核实现的各种锁机制,给出了各种锁机制的特点及其基本用法。
关键词:
Linux内核;同步;锁机制
Abstract:
AimedtoanalyzethefoundationoftheLinuxkernelsynchronizationbyhackingLinuxkernelversion2.4,variouslockingimplementationmechanismsandtheirusagearealsoconcerned.
Keywords:
Linuxkernel;synchronization;lockingmechanism
Linux是支持并发多任务操作系统,Linux内核2.4及以前版本是内核态不可抢占的,也就是说,当正在运行的进程处于内核态时,其他进程(更高优先级的进程)不能通过抢占获得CPU,除非该进程由于某种原因(如等待磁盘数据)自动放弃CPU。
这一特性隐含着处理非阻塞系统调用的内核控制路径间是自动互斥的,只要不是由中断或异常处理程序更新的内核数据结构都可以很安全地被访问。
但事实上系统中存在许多阻塞系统调用(引起进程切换)、处理器异常和外部设备的步中断,这些操作都可在当前进程处于内核态时发生,从而引起内核代码交织执行的情况;从内核版本2.0被引入以来,Linux支持对称多处理器(SMP)系统,多个CPU可以并行运行内核代码。
这样内核数据被多个内核控制路径共享存取,就会产生资源竞争。
根据资源竞争产生的原因及所保护的数据不同,Linux操作系统为内核代码提供了多种同步与互斥机制以保护内核数据的安全共享。
1.操作系统锁机制基本原理
操作系统锁机制的基本原理,就是在某个锁操作过程中不能与其他锁操作交织执行,以免多个执行路径对内核中某些重要的数据及数据结构进行同时操作而造成混乱。
Linux操作系统内核的锁机制一般通过3种基本方式来实现,即原语、关中断和总线锁。
CPU是在每次指令执行结束时检测中断信号的,如果能通过一条指令完成某个操作,则这个操作是原子的,即执行过程过中不会被中断,从而从芯片级保证该操作所存取的数据不能被多个内核控制路径同时访问。
但一般CPU单条指令所涉及的操作有限而且操作很简单,往往只是某个位或整型数的算术逻辑运算,有时为了完成较为复杂的不可中断操作,需要多条指令来完成,这时在单CPU情况下,可采用关中断的方式来避免交叉执行。
此外,在对称多处理器(SMP)环境中,单CPU涉及读-修改-写原语不再是原子的,因为,在某个CPU执行读-修改-写指令时有多次总线操作,其他CPU竞争总线,可导致对同一存储单元的读-写操作与其他CPU对这一存储单元交叉,这时CPU提供了一个前缀操作码lock来锁定总线。
2.Linux内核锁机制的实现
2.1原子操作
根据所存取的数据类型,Linux内核提供了2种类型的原子操作:
位图(bitmaps)和原子类型(atomic)。
位图提供对位的原子操作,主要用于具有分配和释放操作的大量数据单元的管理,如文件系统I节点和磁盘块的分配与释放等。
Linux内核提供对位图操作如表1所示,其中addr为位图地址,nr为位图中的位号。
表1位图原子操作函数原型
函数原型
描述
voidset_bit(intnr,volatilevoid*addr)
设置位图addr中的第nr位
voidclear_bit(intnr,volatilevoid*addr)
清除位图addr中的第nr位
voidchange_bit(intnr,volatilevoid*addr)
改变第nr位的值
inttest_and_set_bit(intnr,volatilevoid*addr)
设置第nr位,并返回设置前的值
inttest_and_clear_bit(intnr,volatilevoid*addr)
清除第nr位,并返回清除前的值
inttest_and_change_bit(intnr,volatilevoid*addr)
改变第nr位,并返回改变前的值
原子类型提供对整型量的加、减等算术运算及测试原子操作。
这种同步方式使用简单且易于理解,如果内核代码希望对整型数据进行同步操作,可把该变量定义为atomic_t类型,然后直接使用如表2所示的原子操作。
表2原子类型操作函数原型
函数原型
描述
atomic_read(&v)
读atomic_t变量v的值
atomic_set(&v,i)
读atomic_t变量v的值
voidatomic_add(intI,volatileatomic_t*v)
设置v的值
voidatomic_sub(inti,volatileatomic_t*v)
减i
intatomic_sub_and_test(inti,volatileatomic_t*v)
减I后,若为0返回1,否则返回0
voidatomic_inc(volatileatomic_t*v)
加1
voidatomic_dec(volatileatomic_t*v)
减1
intatomic_dec_and_test(volatileatomic_t*v)
减1后,若为0返回1,否则返回0
intatomic_inc_and_test(volatileatomic_t*v)
加1后,若为0返回1,否则返回0
intatomic_add_negative(inti,volatileatomic_t*v)
加I后,若小于0返回1,否则返回0
原子操作是其他内核锁机制的基础,通过原子类型操作,可实现信号量和旋转锁机制。
2.2自旋锁(spinlocks)
对较复杂的临界区进行保护,仅有原子操作是不够的。
使用自旋锁就是保护较复杂临界区的方法之一。
一个进程在进入临界区之前,必须取得自旋锁。
进程在获取自旋锁的过程中,如果发现锁不可用(被其他进程占用),该进程一直旋转直到获得该自旋锁。
自旋锁的基本用法如下:
spinlock_tmr_lock=SPIN_LOCK_UNLOCKED;
unsignedlongflags;
spin_lock_irqsave(&mr_lock,flags);
/*临界区…*/
spin_unlock_irqrestore(&mr_lock,flags);
通过使用宏定义,spin_lock_irqsave()在单CPU和SMP下都可使用,在SMP下,spin_lock_irqsave()禁止中断,并提供SMP下的自旋。
在单CPU环境下,上面的程序编译为:
unsignedlongflags;
save_flags(flags);
cli();
/*临界区…*/
restore_flags(flags);
在Linux内核中,还存在3种自旋锁的变体,它们的使用环境如表3所示。
表3自旋锁
自旋锁
用法
spin_lock_irqsave();
spin_unlock_irqrestore();
旋转等待,清中断,保存并恢复标志寄存器;
在获取自旋锁之前,不必清楚中断是否允许。
spin_lock_irq();
spin_unlock_irq();
旋转等待,无条件清中断和设置中断;
在获取自旋锁之前,CPU必须是中断允许的。
spin_lock();
spin_unlock();
仅仅旋转等待,不涉及中断;
用于不可能被中断程序所使用的内核代码,如系统调用。
spin_lock_bh();
spin_unlock_bh();
旋转等待,禁止并恢复软中断;
用于软中断内和软中断外都调用的代码中。
使用自旋锁需注意的是自旋锁不能递归使用,即在拥有某个自旋锁的情况下不能再企图获得该自旋锁,否则将导致系统死锁。
此外,自旋锁实际上是忙等锁,当锁不可用时,CPU一直测试该锁直到可用而取得该锁,表明只有在占用锁的时间极短的情况下,使用自旋锁是合理的。
如果进程获得自旋锁之后再阻塞,也有可能导致死锁的发生。
至于需要较长时间占用锁的情况,Linu内核提供了另一种同步机制即信号量。
2.3信号量(semaphores)
在Linux内核和LinuxSysV用户进程通信中都存在信号量,这里讨论的是Linux内核程序设计中的内核信号量。
与自旋锁不同,信号量是阻塞锁,当进程希望获取锁而锁不可用时,进程把自己阻塞起来,其他进程释放该锁使得锁可用时,再把阻塞进程唤醒。
因此,信号量可用于需要较长时间持有锁的情形。
在使用内核信号量之前,需要通过函数sema_init()对信号量进行初始化,信号量的值可以为0(资源忙)、1(互斥资源空闲)或其他任意正整数n(有n个可用资源)。
获取信号量的函数是down(),它减少信号量并检查信号量的值,如果信号量的值大于或等于0,则当前进程获得资源并正常执行下去;如果信号量的值小于0,则把申请资源的进程放到该信号量的等待队列,并通过调度程序调度其他进程占用CPU。
当进程释放内核信号量时,调用up()函数,该函数增加信号量的值并检查该值;如果信号量的值大于0,则函数正常结束;否则,唤醒该信号量等待队列中的进程。
信号量的一般使用方法如下:
structsemaphoresem;
down(&sem);
/*临界区…*/
up(&sem);
由于标准的down()/up()函数包含阻塞操作,所以down()不能用于中断或中断下部。
为了解决在中断或中断下半部分使用信号量的问题,Linux内核提供了down()函数的一个变体down_trylock(),当资源忙时,该函数不会阻塞进程而直接返回。
此外,在设备驱动程序设计中,希望进程阻塞在设备驱动程序后,还能接受信号以便用户自由处理发生的情况,这时可以使用down()函数的另一变体down_interruptible(),当资源不可用而阻塞后,该进程不仅可被up()唤醒,还可以通过系统信号唤醒。
2.4读/写锁
Linux内核为了存取临界资源而引入了自旋锁和内核信号量,但自旋锁和内核信号量的大量使用反过来会影响内核代码的并发执行。
事实上,内核对临界资源的引用和修改是完全不同类型的操作:
允许多个内核路径同时引用(读)临界资源,而只有修改(写)操作是需要互斥的。
基于该原理,Linux内核在自旋锁和内核信号量的基础上,引入了读/写自旋锁和读/写信号量。
读/写自旋锁的用法与标准自旋锁相似,只是根据对临界资源存取的方式不同而使用不同的锁函数:
rwlock_trwlock=RW_LOCK_UNLOCKED;
read_lock(&rwlock);
/*只读临界区…*/
read_unlock(&rwlock);
write_lock(&rwlock);
/*读/写临界区…*/
write_unlock(&rwlock);
读/写信号量来源于标准信号量,其用法也和标准信号量相同,根据对临界资源的操作是读还是写而使用不同的信号量操作函数:
structrw_semaphorerwsem;
init_rwsem(&rwsem);
down_read(&rwsem);
/*只读临界区…*/
up_read(&rwsem);
down_write(&rwsem);
/*读/写临界区…*/
up_write(&rwsem)
2.5大读锁(big-readerlocks)
大读锁是读/写自旋锁的一种特殊形式。
其特点是获取读锁极快,而获取写锁很慢,所以大读锁一般只用于存在大量读者而写者很少的情形中。
其用法如下:
br_read_lock(BR_LOCK);
/*只读临界区…*/
br_read_unlock(BR_LOCK);
br_write_lock(BR_LOCK);
/*写临界区…*/
br_write_unlock(BR_LOCK);
由于大读锁特有的性质,在Linux内核代码中用得很少,只在其网络核心协议的实现中使用了很少的大读锁。
2.6全局内核锁
全局内核锁又叫大内核锁(bigkernellock),是在内核版本2.0中作为唯一的SMP锁引入的,它通过一个全局锁变量kernel_flag来表达并以自旋锁方式实现。
在当初的SMP实现中,全局内核锁的粒度很粗,任何时刻只允许一个处理器运行在核心态,显然大大限制了多处理器的并行运算。
在2.2~2.5版本的内核中,一方面由于内核变得复杂,大内核锁难以满足要求;另一方面大内核锁效率低,所以把以前由大内核锁同步的某些数据结构改造为由粒度更细的局部内核锁(使用基本的自旋锁)来保护,但现在仍有一些与VFS和网络等相关的数据结构由大内核锁同步。
内核使用lock_kernel()和unlock_kernel()来获取和释放全局锁:
lock_kernel();
/*临界区…*/
unlock_kernel();
3结论
自从内核版本2.0被首次引入SMP以来,Linux内核对SMP支持的可靠性和可扩展性迅速提高,几乎每个后继版本都在前一版本的基础上增加了新的锁原语以提供精巧和高效的锁机制,并通过逐步消除全局内核锁来提高内核并发运行的程度。
为了提高系统的实时性,从内核版本2.5开始,Linux内核变成完全可抢占的,即当前进程无论运行在用户态还是内核态均可被高优先级进程抢占。
一个可抢占内核将导致大量新的竞争同步条件出现,这些新的竞争条件大部分可通过SMP锁自动完成,一些特殊情况需通过引入一些新的方法如preempt_disable()/preempt_enable()来解决。
参考文献:
[1]MichaelB,HaroldB,RobertM。
Linuxkernelinternals[M]。
Boston:
AddisonWesley,1998。
[2]DanielPB,MarcoC。
深入理解Linux内核[M]。
陈莉君,等译。
北京:
中国电力出版社,2001。
[3]WilliamS。
操作系统精髓与设计原理。
第3版[M]。
北京:
清华大学出版社,1998。
[4]ScottM。
LinuxCoreKernelCommentary[M]。
Scottsdale,Arizona:
CoriolisGroup,2000。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 linux 内核