linux主要有几种内核锁,linux内核面试题[1]-Linux中主要有哪几种内核锁

linux内核面试题[1]-Linux中主要有哪几种内核锁

linux主要包括下面的几种内核锁:

<1>互斥锁(mutex)

<2>信号量(semaphore)

<3>自旋锁(spinlock)

<4>读写信号量(rw_semaphore)

<1>互斥锁(mutex)

Mutex: 如果一个线程试图获取一个 mutex,但是没有成功,因为 mutex 已经被占用, 它将进入睡眠,让其他进程运行,直到 mutex 被其他进程释放.

Mutex: 将使得线程睡眠,然后再唤醒它们,两者都是开销比较大的操作,也就是 context switch 的开销.如果锁只是被其他线程占用非常短的时间,那么时间花在使的线程睡眠并唤醒它可能超过它使用 spinlock 持续获取锁的时间.

mutex_init(&mutex);

mutex_lock(&mutex);

mutex_unlock(&mutex);

<2>信号量(semaphore)

信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问该信号量保护的共享资源,初始值为1就变成互斥锁(Mutex),即同时只能有一个任务可以访问信号量保护的共享资源.

一个任务要想访问共享资源,首先必须得到信号量,获取信号量的操作将把信号量的值减1,若当前信号量的值为负数,表明无法获得信号量,该任务必须挂起在该信号量的等待队列等待该信号量可用;若当前信号量的值为非负数,表示可以获得信号量,因而可以立刻访问被该信号量保护的共享资源。当任务访问完被信号量保护的共享资源后,必须释放信号量,释放信号量通过把信号量的值加1实现,如果信号量的值为非正数,表明有任务等待当前信号量,因此它也唤醒所有等待该信号量的任务.

void sema_init (struct semaphore *sem, int val);

该函数用于初始化信号量初始值,设置信号量sem的值为val。

void down(struct semaphore * sem);

该函数用于获取信号量sem,它会导致睡眠,因此不能在中断上下文(包括IRQ上下文和softirq上下文)使用该函数。该函数将把sem的值减1,如果信号量sem的值非负,就直接返回,否则调用者将被挂起,直到别的任务释放该信号量才能继续运行。

int down_interruptible(struct semaphore * sem);

该函数功能与down类似,不同之处为,down不会被信号(signal)打断,但down_interruptible能被信号打断,因此该函数有返回值来区分是正常返回还是被信号中断,如果返回0,表示获得信号量正常返回,如果被信号打断,返回-EINTR。

void up(struct semaphore * sem);

该函数释放信号量sem,即把sem的值加1,如果sem的值为非正数,表明有任务等待该信号量,因此唤醒这些等待者。

<3>自旋锁(spinlock)

Spinlock: 如果一个线程试图获取一个 Spinlock, 但是没有成功,它将持续试着去获取它,直到它最终成功获取,因为它将不允许其他线程运行(然而,操作系统将强制调度其他线程).

Spinlock: Spinlock 持续获取锁,浪费很多 CPU 时间,如果锁被其他线程占用很长时间,那么它将浪费很多时间,不如使得线程进入睡眠,让出 CPU.Spinlock 的确能优化 context switches 但会在没有 threads priority inversion 的平台上产生副作用.(但一个高优先级的线程自旋一个锁来等待一个低优先级的线程释放这个锁,就会造成死锁).在没有 Preemption 的 Uniprocessor,使用 spinlock 是没有意义的,当前只有一个线程运行,没有必要保护关键区域,也没有其他线程同时运行,释放锁给它.

所以在 Linux 下,Spinlock 在 kernel 这样实现:

没有打开CONFIG_SMP和CONFIG_PREEMPT,spinlock 实现代码是空的.

没有打开CONFIG_SMP,打开CONFIG_PREEMPT,spinlock 仅仅是简单的关闭 preemption,足够来防止任何的 races.

打开CONFIG_SMP,打开CONFIG_PREEMPT,不断检查 lock 是否被其他线程释放.

总结

Criteria

Mutex

Spinlock

机制

尝试获取锁.若可得到就占有.若不能,就进入睡眠等待.

尝试获取锁.若可得到就占有.若不能,持续尝试直到获取.

什么时候使用

当线程进入睡眠没有伤害或需要等待一段足够长的时间才能获取锁.

当线程不应该进入睡眠如中断处理等.当只需等待非常短的时间就能获取锁.

缺点

引起 context switch 和 scheduling 开销.

线程不做任何事情在获取到锁前.浪费 CPU 运行.

spin_lock_init(x)、DEFINE_SPINLOCK(x)、SPIN_LOCK_UNLOCKED

spin_is_locked(x)、spin_unlock_wait(x)、spin_trylock(lock)

spin_lock(lock)、spin_unlock(lock)

spin_lock_irqsave(lock, flags)、spin_unlock_irqrestore(lock, flags)

spin_lock_irq(lock)、spin_unlock_irq(lock)

spin_lock_bh(lock)、spin_unlock_bh(lock)

spin_trylock_irqsave(lock, flags)

spin_trylock_irq(lock)

<4>读写信号量(rw_semaphore)

读写信号量对访问者进行了细分,或者为读者,或者为写者,读者在保持读写信号量期间只能对该读写信号量保护的共享资源进行读访问,如果一个任务除了需要读,可能还需要写,那么它必须被归类为写者,它在对共享资源访问之前必须先获得写者身份,写者在发现自己不需要写访问的情况下可以降级为读者。读写信号量同时拥有的读者数不受限制,也就说可以有任意多个读者同时拥有一个读写信号量。如果一个读写信号量当前没有被写者拥有并且也没有写者等待读者释放信号量,那么任何读者都可以成功获得该读写信号量;否则,读者必须被挂起直到写者释放该信号量。如果一个读写信号量当前没有被读者或写者拥有并且也没有写者等待该信号量,那么一个写者可以成功获得该读写信号量,否则写者将被挂起,直到没有任何访问者。因此,写者是排他性的,独占性的。

参考资料

【1】https://www.ibm.com/developerworks/cn/linux/l-synch/part1/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值