Linux中提供的并发控制机制

本文介绍了Linux操作系统中用于解决多任务并发问题的几种核心机制:原子操作、自旋锁及信号量。通过这些机制,可以有效地避免多进程间的资源竞争问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

由于Linux是一个支持多任务的操作系统,多个进程之间是一种并发的关系。并发是指在操作系统中,一个时间段中有几个程序都处于已启动运行到运行完毕之间,但在任一时间点上只有一个进程在处理器上运行。并发容易导致竞争的问题,竞争就是两个或两个以上的进程同时访问同一资源,从而引起资源的错误。这是操作系统运行所不允许的,所以内核中提供了一些并发控制的机制,用于对公共资源进行保护。

 

下面描述的相应机制的API都是ARM架构下的实现

 

(1)  原子操作

原子操作是一种在操作过程中不允许被打断的操作,所以在内核驱动程序中非常有用。原子操作需要硬件支持,所以是架构相关的

 

类型: atomic_t     定义在include/linux/types.h中

typedef struct {
    int counter;
} atomic_t;

 

相关的API  实现在arch/arm/include/asm/atomic.h

18 #define ATOMIC_INIT(i)  { (i) }
27 #define atomic_read(v)  (*(volatile int *)&(v)->counter)
28 #define atomic_set(v,i) (((v)->counter) = (i)

 37 static inline void atomic_add(int i, atomic_t *v)
 38 {
 39         unsigned long tmp;
 40         int result;
 41 
 42         __asm__ __volatile__("@ atomic_add\n"
 43 "1:     ldrex   %0, [%3]\n"
 44 "       add     %0, %0, %4\n"
 45 "       strex   %1, %0, [%3]\n"
 46 "       teq     %1, #0\n"
 47 "       bne     1b"
 48         : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
 49         : "r" (&v->counter), "Ir" (i)
 50         : "cc");
 51 }
 75 static inline void atomic_sub(int i, atomic_t *v)
 76 {
 77         unsigned long tmp;
 78         int result;
 79 
 80         __asm__ __volatile__("@ atomic_sub\n"
 81 "1:     ldrex   %0, [%3]\n"
 82 "       sub     %0, %0, %4\n"
 83 "       strex   %1, %0, [%3]\n"
 84 "       teq     %1, #0\n"
 85 "       bne     1b"
 86         : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
 87         : "r" (&v->counter), "Ir" (i)
 88         : "cc");
 89 }
221 #define atomic_inc(v)           atomic_add(1, v)
222 #define atomic_dec(v)           atomic_sub(1, v)
223 
224 #define atomic_inc_and_test(v)  (atomic_add_return(1, v) == 0)
225 #define atomic_dec_and_test(v)  (atomic_sub_return(1, v) == 0)
226 #define atomic_inc_return(v)    (atomic_add_return(1, v))
227 #define atomic_dec_return(v)    (atomic_sub_return(1, v))
228 #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)


(2) 自旋锁
类型: spinlock_t    定义在include/linux/spinlock_types.h中

 17 typedef struct {
 18         volatile unsigned int slock;
 19 } arch_spinlock_t;
 20 typedef struct raw_spinlock {
 21         arch_spinlock_t raw_lock;
 22 #ifdef CONFIG_GENERIC_LOCKBREAK
 23         unsigned int break_lock;
 24 #endif
 25 #ifdef CONFIG_DEBUG_SPINLOCK
 26         unsigned int magic, owner_cpu;
 27         void *owner;
 28 #endif
 29 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 30         struct lockdep_map dep_map;
 31 #endif
 32 } raw_spinlock_t;
 64 typedef struct spinlock {
 65         union {
 66                 struct raw_spinlock rlock;
 67 
 68 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 69 # define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
 70                 struct {
 71                         u8 __padding[LOCK_PADSIZE];
 72                         struct lockdep_map dep_map;
 73                 };
 74 #endif
 75         };
 76 } spinlock_t;

 

相应的API操作函数    在include/linux/spinlock.h中

a>初始化锁

277 #define spin_lock_init(_lock)                           \
278 do {                                                    \
279         spinlock_check(_lock);                          \
280         raw_spin_lock_init(&(_lock)->rlock);            \
281 } while (0)
103 # define raw_spin_lock_init(lock)                               \
104         do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0)
 59 #define __RAW_SPIN_LOCK_UNLOCKED(lockname)      \
 60         (raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)
 53 #define __RAW_SPIN_LOCK_INITIALIZER(lockname)   \
 54         {                                       \
 55         .raw_lock = __ARCH_SPIN_LOCK_UNLOCKED,  \
 56         SPIN_DEBUG_INIT(lockname)               \
 57         SPIN_DEP_MAP_INIT(lockname) }
12 #define __ARCH_SPIN_LOCK_UNLOCKED       { 1 }

 

spin_lock_init(spinlock_t *)

          --> raw_spin_lock_init(raw_spinlock_t *)

                    --> __RAW_SPIN_LOCK_UNLOCKED(raw_spinlock_t *)  

                           --> __RAW_SPIN_LOCK_INITIALIZER(raw_spinlock_t *)

                                     --> __ARCH_SPIN_LOCK_UNLOCKED   

实际上,也就是将锁初始化为1            

 

b>请求锁

283 static inline void spin_lock(spinlock_t *lock)
284 {
285         raw_spin_lock(&lock->rlock);
286 }
170 #define raw_spin_lock(lock)     _raw_spin_lock(lock)
135 void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
136 {
137         __raw_spin_lock(lock);
138 }
139 EXPORT_SYMBOL(_raw_spin_lock);


c> 解锁

323 static inline void spin_unlock(spinlock_t *lock)
324 {
325         raw_spin_unlock(&lock->rlock);
326 }


(3)  信号量

与自旋锁一样,信号量也是用来保护临界资源的一种方式
类型:struct semaphore    定义在include/linux/semaphore.h中

 16 struct semaphore {
 17         raw_spinlock_t          lock;
 18         unsigned int            count;
 19         struct list_head        wait_list;
 20 };

 

相关API

a> 定义一个信号量

29 #define DEFINE_SEMAPHORE(name)  \
30         struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)


b> 初始化一个信号量 (计数为1)

 22 #define __SEMAPHORE_INITIALIZER(name, n)                                \
 23 {                                                                       \
 24         .lock           = __RAW_SPIN_LOCK_UNLOCKED((name).lock),        \
 25         .count          = n,                                            \
 26         .wait_list      = LIST_HEAD_INIT((name).wait_list),             \
 27 }


c> 请求信号量 (请求不到就sleep, 直到得到信号量或中断/kill signal才返回)

75 int down_interruptible(struct semaphore *sem)
101 int down_killable(struct semaphore *sem)

 

130 int down_trylock(struct semaphore *sem)  //请求不到就返回,不进行sleep

d> 释放信号量

178 void up(struct semaphore *sem)



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值