Linux Kernel semaphore, mutex, spinlock

1. semaphore

1.1 concept

Semaphore also known as light (semaphore), which is used to coordinate data objects between different processes, semaphores essentially a counter, which is used to record the status of access to a resource (such as shared memory). In general, in order to obtain a shared resource, the process needs to do the following:
   (1) the amount of the test control signal resource.
   (2) If this semaphore value is positive, it is allowed to use the resource. The process signal minus 1.
   (3) If this signal is 0, the resource is currently unavailable, the process goes to sleep until the signal magnitude is greater than 0, the process is awakened, go to step (1).
   (4) when the process no longer uses a resource amount control signal, the signal magnitude plus one. If the process is sleeping at this time there waiting for this semaphore, it wakes up this process.

1.2 relates to the structure, function

/* 从以上信号量的定义中,可以看到信号量底层使用到了spin lock的锁定机制,这个spinlock主要用来确保对count成员的原子性的操作(count--)和测试(count > 0)。 */
struct semaphore {
        spinlock_t                lock;
        unsigned int             count;
        struct list_head        wait_list;
};

(1) Get semaphore operation

#
(1).void down(struct semaphore *sem);   //废弃


/*  (最常用)
    在保证原子操作的前提下,先测试count是否大于0,
    ~ 如果是说明可以获得信号量,这种情况下需要先将count--,以确保别的进程能否获得该信号量,然后函数返回,其调用者开始进入临界区。
    ~ 如果没有获得信号量,当前进程利用struct semaphore 中wait_list加入等待队列,开始睡眠。
*/
(2).int down_interruptible(struct semaphore *sem);


/* 试图去获得一个信号量,如果没有获得,函数立刻返回1而不会让当前进程进入睡眠状态。 */
(3).int down_trylock(struct semaphore *sem);

2) a release semaphore operation

/*  如果没有其他线程等待在目前即将释放的信号量上,那么只需将count++即可。如果有其他线程正因为等待该信号量而睡眠,那么调用__up唤醒睡眠的进程*/
void up(struct semaphore *sem);

2. mutex

2.1 Concepts

Mutex to achieve a "mutually exclusive" (mutual exclusion) simple form of synchronization (so named mutex (mutex)). Mutex prohibit multiple threads at the same time to enter the protected code "critical area" (critical section). Thus, at any time, only one thread is permitted to enter protected areas such code. count = semaphore mutex is actually a case of one.

2.2 relates to the structure, function

// 结构
struct mutex {
        /* 1: unlocked, 0: locked, negative: locked, possible waiters */
        atomic_t                  count;
        spinlock_t                wait_lock;
        struct list_head          wait_list;
#ifdef CONFIG_DEBUG_MUTEXES
        struct thread_info        *owner;
        const char                *name;
        void                      *magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map         dep_map;
#endif
};
// 定义互斥锁lock
mutex_init(struct mutex* lock)

// 获取
 mutex_lock(struct mutex *lock)

// 释放
 mutex_unlock(struct mutex *lock)

3. spin locks

3.1 Definitions

At any time, at most one holder, it said, you can only have at most one execution unit at any time to acquire a lock. But the two slightly different scheduling mechanisms.
~ For the mutex, if the resource is already occupied, the resource request can only go to sleep.
~ But the spin lock without causing the caller to sleep, if the spin lock has been held another execution unit, the caller has been to see whether the spin cycle lock holder has released the lock there, "spin" a word is so named.
- The biggest difference is the spin lock will not sleep

3.2 relates to the structure, function

# linux/Spinlock.h
typedef struct spinlock {
          union { //联合
             struct raw_spinlock rlock;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
             struct{
                     u8 __padding[LOCK_PADSIZE];
                     struct lockdep_map dep_map;
             };
#endif
         };
} spinlock_t;
//定义与初始化
spinlock_t my_lock = SPIN_LOCK_UNLOCKED; 
void spin_lock_init(spinlock_t *lock); 

//加锁一个自旋锁函数
void spin_lock(spinlock_t *lock);                                   //获取指定的自旋锁
void spin_lock_irq(spinlock_t *lock);                               //禁止本地中断获取指定的锁
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);      //保存本地中断的状态,禁止本地中断,并获取指定的锁
void spin_lock_bh(spinlock_t *lock)                                 //安全地避免死锁, 而仍然允许硬件中断被服务


//释放一个自旋锁函数
void spin_unlock(spinlock_t *lock);                                 //释放指定的锁
void spin_unlock_irq(spinlock_t *lock);                             //释放指定的锁,并激活本地中断
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); //释放指定的锁,并让本地中断恢复到以前的状态
void spin_unlock_bh(spinlock_t *lock);                              //对应于spin_lock_bh


//非阻塞锁
int spin_trylock(spinlock_t *lock);                  //试图获得某个特定的自旋锁,如果该锁已经被争用,该方法会立刻返回一个非0值,
                                                     //而不会自旋等待锁被释放,如果成果获得了这个锁,那么就返回0.
int spin_trylock_bh(spinlock_t *lock);                           
//这些函数成功时返回非零( 获得了锁 ), 否则 0. 没有"try"版本来禁止中断.

//其他
int spin_is_locked(spinlock_t *lock);               //和try_lock()差不多

4. Comparative spinlock & mutex

Semaphore / mutex lock to allow the process to sleep belong to sleep, spin lock the caller does not sleep, but let it wait cycle, so there is less difference between the application
1), semaphores and read-write semaphores is adapted to hold a more time long, they can cause the caller to sleep, and therefore suitable for holding a spin lock time is very short case
2), the spin lock can be used to interrupt, it can not be used to process context (cause a deadlock). The semaphore is not allowed in the interrupt, and can be used to process context
3), the spin lock hold period is to seize the failure, when the spin lock is held, the kernel can not be preempted, and semaphores and read-write semaphores during the hold can be preempted

5. & mutex semaphore

Use: the semaphore is mainly applied to inter-process communication, of course, also be used for inter-thread communication. The mutex can only be used for communication between threads.

Guess you like

Origin blog.csdn.net/yuewen2008/article/details/83780544