湖北 网站建设,分类信息网,西安百度竞价推广,百度推广关键词#x1f525; 推荐#xff1a;《Yocto项目实战教程#xff1a;高效定制嵌入式Linux系统》 京东正版促销#xff0c;欢迎支持原创#xff01; 链接#xff1a;https://item.jd.com/15020438.html 一、为什么需要同步机制#xff1f;
Linux 是一个支持 多核并发 抢占式调… 推荐《Yocto项目实战教程高效定制嵌入式Linux系统》 京东正版促销欢迎支持原创 链接https://item.jd.com/15020438.html 一、为什么需要同步机制
Linux 是一个支持 多核并发 抢占式调度 的操作系统多个内核线程可能同时访问同一份内存区域例如驱动共享某个全局变量、文件系统缓存读写、网络缓冲区处理等等。
如果没有同步机制就会产生竞态条件Race Condition导致数据错乱、内核崩溃甚至安全漏洞。
因此Linux 内核实现了一整套高效的同步机制用来协调不同 CPU、不同执行上下文之间对共享资源的访问。 二、Linux 中的主要同步机制
同步机制是否可睡眠适用场景常见用法内核位置原子变量否简单计数/标志状态标志、自增自减include/linux/atomic.h自旋锁否中断处理、短临界区硬件寄存器、短时间保护include/linux/spinlock.h信号量是多资源管理限制并发访问数include/linux/semaphore.h互斥锁是临界区保护普通数据结构保护include/linux/mutex.hRCU部分读者无锁读多写少的表结构任务列表、网络表项kernel/rcu/ 三、五种同步机制逐一讲解
3.1 原子变量
✅ 场景状态标志、自增计数器
atomic_t count;
atomic_set(count, 0);atomic_inc(count); // count
atomic_dec(count); // --countif (atomic_read(count) 0) {// 说明资源清空或条件满足
}原子变量适合简短逻辑如计数器、标志位。不适合保护复杂数据结构。
✅ 面试考点
原子变量是否需要锁→ 否。原子操作能否用于中断上下文→ 可以。 3.2 自旋锁Spinlock
✅ 场景短时间保护、中断上下文
spinlock_t my_lock;
spin_lock_init(my_lock);spin_lock(my_lock);
/* 访问共享资源 */
spin_unlock(my_lock);推荐《Yocto项目实战教程高效定制嵌入式Linux系统》 京东正版促销欢迎支持原创 链接https://item.jd.com/15020438.html ✅ 中断安全版本
unsigned long flags;
spin_lock_irqsave(my_lock, flags);
/* 临界区 */
spin_unlock_irqrestore(my_lock, flags);✅ 特点
获取不到锁会 原地忙等自旋适合快速操作不可用于睡眠上下文否则死锁常用于中断处理函数、底半部等高优先级逻辑。
✅ 面试考点
spin_lock 与 mutex 有什么区别中断上下文是否可以使用 mutex→ 否。 3.3 信号量Semaphore
✅ 场景控制多个线程对有限资源访问
struct semaphore sem;
sema_init(sem, 3); // 最多允许3个并发/* 请求资源 */
down(sem); // 若资源不足将睡眠/* 使用资源 *//* 释放资源 */
up(sem);适合表示资源池如“3台打印机”、“10个缓存槽位”已逐渐被 mutex 替代。
✅ 面试考点
down()/up() 会阻塞线程吗→ 是。信号量适合中断中使用吗→ 否会睡眠。 3.4 互斥锁Mutex
✅ 场景线程间对共享数据的互斥访问
struct mutex my_mutex;
mutex_init(my_mutex);mutex_lock(my_mutex);
/* 临界区代码 */
mutex_unlock(my_mutex);获取不到锁会让当前线程 挂起等待资源释放后再调度回来不适合中断处理。
✅ 特点对比
比较项spinlockmutex可否睡眠否是场景中断/底半部普通线程获取失败自旋等待睡眠等待
✅ 面试考点
mutex 和 semaphore 区别→ semaphore 是计数mutex 仅一人。 3.5 RCURead-Copy-Update
✅ 场景读多写少如任务列表、网络表项
读操作不加锁
rcu_read_lock();
my_ptr rcu_dereference(global_ptr);
/* 安全读取数据 */
rcu_read_unlock();写操作复制更新
new_ptr kmalloc(...);
/* 修改副本 */
rcu_assign_pointer(global_ptr, new_ptr);
synchronize_rcu();
/* 释放旧数据 */
kfree(old_ptr);✅ 特点
读性能极高不加锁写复杂需注意数据生命周期常用于链表、哈希表等结构。
✅ 面试考点
RCU 是否支持多读多写→ 多读 单写 延迟销毁。RCU 与普通锁最大区别→ 读时不阻塞。 四、实战示例共享计数器保护
❌ 错误示例未加锁
static int count 0;void do_work(void) {count; // 多线程访问存在竞态
}✅ 正确方式使用原子变量
static atomic_t count ATOMIC_INIT(0);void do_work(void) {atomic_inc(count);
}✅ 或使用自旋锁
static int count 0;
static spinlock_t lock;void do_work(void) {spin_lock(lock);count;spin_unlock(lock);
}✅ 或使用 mutex若可睡眠
static int count 0;
static struct mutex my_mutex;void do_work(void) {mutex_lock(my_mutex);count;mutex_unlock(my_mutex);
}五、面试常见问题汇总含答案 spinlock 和 mutex 有何区别 spinlock 不可睡眠、适用于中断上下文mutex 会睡眠、适合线程间同步。 原子变量需要加锁吗 不需要已具备原子性。 哪些锁不能用于中断 mutex、semaphore 会睡眠不能用于中断处理。 RCU 为什么性能高 读操作无锁不阻塞任何线程极高并发性。 如何避免死锁 保持锁获取顺序一致禁止在持锁时调用睡眠函数如 mutex msleep()中断上下文避免调用可睡眠接口。 六、小结如何选用同步机制
场景建议同步方式标志位、计数器原子变量中断处理、底半部自旋锁用户进程临界区互斥锁 mutex限制访问数量N个资源信号量 semaphore读多写少表结构RCU 七、结束语
Linux 内核的同步机制是驱动开发和内核编程中的“必修课”掌握好它不仅能写出正确的代码更是迈入高级内核开发的关键一步。 推荐《Yocto项目实战教程高效定制嵌入式Linux系统》 京东正版促销欢迎支持原创 链接https://item.jd.com/15020438.html 视频教程请关注 B 站“嵌入式 Jerry”