面试题3:Linux中的锁锁锁!!!

一、读写锁

读写锁,也叫作共享式互斥锁。有3种状态:读模式的加锁状态、写模式的加锁状态、不加锁状态。

写模式加锁状态:在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。

读模式加锁状态:所有试图以读模式进行加锁的线程都可以得到访问权,但是任何希望以写模式对此加锁的线程都会阻塞,直到所有的线程释放他们的读锁为止。

读写锁非常适合于对数据结构读的次数远大于写的情况。

二、自旋锁

自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。

由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。

信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用(_trylock的变种能够在中断上下文使用),而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。

如果被保护的共享资源只在进程上下文访问,使用信号量保护该共享资源非常合适,如果对共巷资源的访问时间非常短,自旋锁也可以。但是如果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就必须使用自旋锁。

自旋锁保持期间是抢占失效的,而信号量和读写信号量保持期间是可以被抢占的。自旋锁只有在内核可抢占或SMP的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作。

跟互斥锁一样,一个执行单元要想访问被自旋锁保护的共享资源,必须先得到锁,在访问完共享资源后,必须释放锁。如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即得到锁;如果在获取自旋锁时锁已经有保持者,那么获取锁操作将自旋在那里,直到该自旋锁的保持者释放了锁

无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。

三、RCU

首先我们从概念上理解下什么叫RCU,其中读(Read):读者不需要获得任何锁就可访问RCU保护的临界区;拷贝(Copy):写者在访问临界区时,写者“自己”将先拷贝一个临界区副本,然后对副本进行修改;更新(Update):RCU机制将在在适当时机使用一个回调函数把指向原来临界区的指针重新指向新的被修改的临界区,锁机制中的垃圾收集器负责回调函数的调用。总结即是读-拷贝-更新。

linux下的锁机制

——————————————————————————————————————————————

我们将採取下面的样例来解释为什么须要使用文件锁。

1、  进程“A”打开和读取一个文件,此文件包括账户相关的一些信息。

2、  进程“B”也打开了这个文件。并读取了文件里的信息。

3、  如今,进程“A”更改了其副本中的一条剩余金额记录,并将其写入文件。

4、  此时,进程“B”并不知道上次读取的文件已经被更改。它还保存着原始的文件副本。然后。进程“B”更改了“A”操作的那条同样的记录,并将记录写入文件。

5、  此时。文件里将仅仅保存了进程“B”更改过的记录。

为了避免这样的事情发生,就要使用文件锁来确保操作的“序列化”。

Linux系统中两种经常使用的文件锁:

1、  协同锁

协同锁要求參与操作的进程之间协同合作。

如果进程“A”获得一个WRITE锁,并開始向文件里写入内容;此时,进程“B”并没有试图获取一个锁,它仍然能够打开文件并向文件里写入内容。

在此过程中,进程“B”就是一个非合作进程。如果进程“B”试图获取一个锁,那么整个过程就是一个合作的过程,从而能够保证操作的“序列化”。

仅仅有当參与操作的进程是协同合作的时候,协同锁才干发挥作用。协同锁有时也被称为“非强制”锁。

2、  强制锁

强制锁不须要參与操作的进程之间保持协同合作。它利用内核来查检每一个打开、读取、写入操作,从而保证在调用这些操作时不违反文件上的锁规则。关于强制锁的很多其它信息,能够在kernal.org上找到。

为了使能Linux中的强制锁功能。你须要在文件系统级别上打开它。同一时候在单个文件上打开它。其步骤是:

1、  挂载文件系统时使用“-o mand”參数。

2、  对于要打开强制锁功能的文件lock_file。必须打开set-group-ID位。关闭group-execute位。

(选择此方法的原因是,当你关闭group-execute时,设置set-group-ID就没有实际的意义了)

Linux以下的两种文件锁

猜你喜欢

转载自blog.csdn.net/wangdd_199326/article/details/81321775