linux内核互斥锁

Linux内核互斥锁
/linux/include/linux/mutex.h
      47struct mutex { 
      48         
      49        atomic_t                count; 
      50        spinlock_t              wait_lock; 
      51        struct list_head        wait_list; 
      52#ifdef CONFIG_DEBUG_MUTEXES 
      53        struct thread_info      *owner; 
      54        const char              *name; 
      55        void                    *magic; 
      56#endif 
      57#ifdef CONFIG_DEBUG_LOCK_ALLOC 
      58        struct lockdep_map      dep_map; 
      59#endif 
      60};
 
一、作用及访问规则:
互斥锁主要用于实现内核中的互斥访问功能。内核互斥锁是在原子 API 之上实现的,但这对于内核用户是不可见的。对它的访问必须遵循一些规则:同一时间只能有一个任务持有互斥锁,而且只有这个任务可以对互斥锁进行解锁。互斥锁不能进行递归锁定或解锁。一个互斥锁对象必须通过其API初始化,而不能使用memset或复制初始化。一个任务在持有互斥锁的时候是不能结束的。互斥锁所使用的内存区域是不能被释放的。使用中的互斥锁是不能被重新初始化的。并且互斥锁不能用于中断上下文。但是互斥锁比当前的内核信号量选项更快,并且更加紧凑,因此如果它们满足您的需求,那么它们将是您明智的选择。
 
二、各字段详解:
1、atomic_t count; --指示互斥锁的状态:1 没有上锁,可以获得;0 被锁定,不能获得;负数 被锁定,且可能在该锁上有等待进程初始化为没有上锁。
2、spinlock_t wait_lock; --等待获取互斥锁中使用的自旋锁。在获取互斥锁的过程中,操作会在自旋锁的保护中进行。初始化为为锁定。
3、struct list_head wait_list; --等待互斥锁的进程队列。
 
四、操作:
1、定义并初始化:
struct mutex mutex;
mutex_init(&mutex);
 
      79# define mutex_init(mutex) /
      80do { /
      81 static struct lock_class_key __key; /
      82 /
      83 __mutex_init((mutex), #mutex, &__key); /
      84} while (0)
 
      42void
      43__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
      44{
      45 atomic_set(&lock->count, 1);
      46 spin_lock_init(&lock->wait_lock);
      47 INIT_LIST_HEAD(&lock->wait_list);
      48
      49 debug_mutex_init(lock, name, key);
      50}
 
直接定于互斥锁mutex并初始化为未锁定,己count为1,wait_lock为未上锁,等待队列wait_list为空。
 
2、获取互斥锁:
(1)具体参见linux/kernel/mutex.c
void inline __sched mutex_lock(struct mutex *lock)
{
 might_sleep();
 
 __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
}
获取互斥锁。实际上是先给count做自减操作,然后使用本身的自旋锁进入临界区操作。首先取得count的值,再将count置为-1,判断如果原来count的值为1,也即互斥锁可以获得,则直接获取,跳出。否则进入循环反复测试互斥锁的状态。在循环中,也是先取得互斥锁原来的状态,再将其置为-1,判断如果可以获取(等于1),则退出循环,否则设置当前进程的状态为不可中断状态,解锁自身的自旋锁,进入睡眠状态,待被在调度唤醒时,再获得自身的自旋锁,进入新一次的查询其自身状态(该互斥锁的状态)的循环。
 
(2)具体参见linux/kernel/mutex.c
int __sched mutex_lock_interruptible(struct mutex *lock)
{
       might_sleep();
       return __mutex_fastpath_lock_retval(&lock->count, __mutex_lock_interruptible_slowpath);
}
和mutex_lock()一样,也是获取互斥锁。在获得了互斥锁或进入睡眠直到获得互斥锁之后会返回0。如果在等待获取锁的时候进入睡眠状态收到一个信号(被信号打断睡眠),则返回_EINIR。
 
(3)具体参见linux/kernel/mutex.c
int __sched mutex_trylock(struct mutex *lock)
{
 return __mutex_fastpath_trylock(&lock->count,
     __mutex_trylock_slowpath);
}
试图获取互斥锁,如果成功获取则返回1,否则返回0,不等待。
 
3、释放互斥锁:
具体参见linux/kernel/mutex.c
void __sched mutex_unlock(struct mutex *lock)
{
        
       __mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
}
释放被当前进程获取的互斥锁。该函数不能用在中断上下文中,而且不允许去释放一个没有上锁的互斥锁。
 
4.void mutex_destroy(struct mutex *lock) --清除互斥锁,使互斥锁不可用
用mutex_destroy()函数解除由lock指向的互斥锁的任何状态。在调用执行这个函数的时候,lock指向的互斥锁不能在被锁状态。储存互斥锁的内存不被释放。
返回值--mutex_destroy()在成功执行后返回零。其他值意味着错误。在以下情况发生时,函数失败并返回相关值。
EINVAL 非法参数
EFAULT mp指向一个非法地址。
5.static inline int mutex_is_locked(struct mutex *lock)--测试互斥锁的状态
这个调用实际上编译成一个内联函数。如果互斥锁被持有(锁定),那么就会返回 1;否则,返回 0。
 
五、使用形式:
struct mutex mutex;
mutex_init(&mutex);
...
mutex_lock(&mutex);
...
mutex_unlock(&mutex);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值