linux同步策略

news/2024/9/22 20:28:34/文章来源:https://www.cnblogs.com/lihaoxiang/p/18425804

Linux 驱动层,由于多个进程或内核线程可能同时访问共享资源,必须使用同步机制来防止数据竞争和不一致性。同步机制的主要目的是保证多线程或多进程在并发访问共享资源时不发生冲突或数据损坏。Linux 提供了多种同步机制来应对不同的并发场景。

常见的 Linux 驱动层同步机制:

1. 原子操作(Atomic Operations)

原子操作是不可中断的基本操作,通常用于对简单的数据类型(如整数、位)执行操作,保证在多线程环境中,操作不会被中断或部分执行。

  • 常见操作atomic_inc()atomic_dec()atomic_set()atomic_read() 等。
  • 适用场景:用于对整数等简单变量进行简单的加减、置位操作。

示例

atomic_t counter;
atomic_set(&counter, 0);
atomic_inc(&counter);

2. 自旋锁(Spinlock)

自旋锁(Spinlock) 是一种忙等待的锁机制,当一个进程或线程试图获取自旋锁时,如果锁已被占用,进程会在原地持续“旋转”(自旋)等待,直到锁被释放。它不会进入休眠状态,因此适用于锁持有时间非常短的场景。

  • 常见操作spin_lock()spin_unlock()
  • 适用场景:短时间的临界区保护,特别是中断处理程序中,或者在需要禁用抢占的场景下使用。

示例

spinlock_t my_lock;
spin_lock_init(&my_lock);spin_lock(&my_lock);
// 临界区代码
spin_unlock(&my_lock);
  • 自旋锁与中断:在处理器中断上下文使用自旋锁时,需要确保禁用中断,防止中断期间重新尝试获取锁导致死锁。
    • spin_lock_irqsave():在获取锁的同时禁用中断。
    • spin_unlock_irqrestore():释放锁并恢复中断状态。

3. 信号量(Semaphore)

信号量是一种计数器,用于控制对共享资源的访问。与自旋锁不同,信号量可以导致进程睡眠而不是忙等待,适用于较长时间的资源争用情况。信号量允许一定数量的进程/线程同时访问资源。

  • 常见操作down()up()
  • 适用场景:当进程需要等待某个资源并可以进入休眠时(例如在 I/O 操作中)。

示例

struct semaphore my_sem;
sema_init(&my_sem, 1);down(&my_sem);  // 获取信号量(可能会进入睡眠)
/* 临界区 */
up(&my_sem);    // 释放信号量

4. 互斥量(Mutex)

互斥量(Mutex) 是一个二值的信号量,保证同一时间只有一个线程或进程能够访问临界区。与信号量类似,互斥量也会导致线程睡眠,而不是忙等待。互斥量特别适合用于单一持有者场景,即同一时间只有一个线程/进程需要访问资源。

  • 常见操作mutex_lock()mutex_unlock()
  • 适用场景:用于长时间持有的锁,尤其是资源访问可能会涉及睡眠操作时(例如等待 I/O 设备)。

示例

struct mutex my_mutex;
mutex_init(&my_mutex);mutex_lock(&my_mutex);
/* 临界区代码 */
mutex_unlock(&my_mutex);

5. 读写锁(Read-Write Lock)

读写锁允许多个读取者同时获取锁,但在写操作时,只有一个写入者能够获取锁,并且阻塞所有读取操作。读写锁特别适合读多写少的场景。

  • 常见操作

    • rwlock_t 相关操作:read_lock()read_unlock()write_lock()write_unlock()
  • 适用场景:多读少写的并发场景下,能够提高读取性能。

示例

rwlock_t rw_lock;
rwlock_init(&rw_lock);read_lock(&rw_lock);
// 读取临界区代码
read_unlock(&rw_lock);write_lock(&rw_lock);
// 写入临界区代码
write_unlock(&rw_lock);

6. 完成量(Completion)

完成量(Completion) 用于进程间同步,常见于等待某个事件完成后再继续执行。它允许一个进程等待另一个进程完成某个操作。

  • 常见操作init_completion()wait_for_completion()complete()
  • 适用场景:用于同步多个进程,确保某个任务或操作完成。

示例

struct completion my_completion;
init_completion(&my_completion);// 在其他地方调用
complete(&my_completion);  // 触发完成信号// 等待完成信号
wait_for_completion(&my_completion);

7. 顺序锁(Seqlock)

顺序锁(Seqlock) 适用于写少读多的场景。顺序锁通过一个计数器来保证数据一致性,允许读取操作不阻塞写入操作,但读取操作如果遇到写入,则必须重新读取。

  • 常见操作write_seqlock()write_sequnlock()read_seqbegin()read_seqretry()
  • 适用场景:读多写少的场景,尤其是对性能要求较高的地方。

示例

seqlock_t my_seqlock;
seqlock_init(&my_seqlock);unsigned int seq;
do {seq = read_seqbegin(&my_seqlock);// 读取数据
} while (read_seqretry(&my_seqlock, seq));

8. RCU(Read-Copy-Update)

RCU(Read-Copy-Update) 是一种高效的读写同步机制,允许在没有锁的情况下并发读取数据,写入数据时则会创建一个数据副本。写入操作的修改不会影响正在进行的读取操作,直到读者完成读取。

  • 常见操作

    • 读操作:rcu_read_lock()rcu_read_unlock()
    • 写操作:synchronize_rcu()call_rcu()
  • 适用场景:适用于读写性能要求极高的场景,尤其是内核中某些对性能要求高的并发数据结构。

示例

rcu_read_lock();
// 读取临界区代码
rcu_read_unlock();// 在写入时同步
synchronize_rcu();

总结

Linux 驱动开发中,选择合适的同步机制是确保并发场景下数据一致性和性能的关键。不同的同步机制适用于不同的场景:

  • 原子操作:用于简单的整数和位操作。
  • 自旋锁:用于短时间的锁,适合中断上下文。
  • 信号量和互斥量:用于进程/线程之间长时间锁定资源,支持睡眠。
  • 读写锁:多读少写场景下提高读性能。
  • 完成量:用于同步操作的完成。
  • 顺序锁:提高写少读多场景下的性能。
  • RCU:在高并发场景中提供高效的读写操作。

根据实际需求选择合适的同步机制,可以有效提高驱动程序的性能和稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/801679.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单机版 ClickHouse 部署和 SpringBoot 程序访问

ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的列式存储数据库(DBMS),使用C++语言编写,主要用于在线分析处理查询(OLAP),能够使用SQL查询实时生成分析数据报告。 OLAP 为联机分析处理,专注于统计查询;OLTP 为联机事务处理,专注于增删改。 ClickHouse 的优势在于单表…

self supervised learning

self supervised learning 自监督学习,按照机器学习中传统分类方法,监督学习,无监督学习,强化学习,有些还会有半监督学习等。 监督学习,以计算机视觉领域中最简单的任务为例,给你一张只有一只狗的图,让你说这图是什么,你肯定说是狗。那么在计算机视觉任务重,给这图打…

用户验收测试指南8实施测试

8 实施测试 到目前为止,我们已经规划了我们的 UAT 演习,并制定了测试的总体战略,然后设计了所有测试并编写了测试脚本。现在,我们已准备好实施计划和进行测试。 在本章中,我们将介绍如何安排所有测试,以实现我们的测试策略,并根据验收标准评估系统。为此,我们需要记录所…

Linux中删除文本中所有的重复的字符保持唯一

001、[root@PC1 test]# ls a.txt [root@PC1 test]# cat a.txt ## 测试文本 abk akkkkccc 8777 ,,, aaaf 333444 --- uukk22 [root@PC1 test]# cat a.txt | tr -s [:alnum:] ## 删除连续的重复字符 abk akc 87 ,,, af 34 --- uk2 [root@PC1 test]# …

ConcurrentLinkedQueue详解(图文并茂)

前言 ConcurrentLinkedQueue是基于链接节点的无界线程安全队列。此队列按照FIFO(先进先出)原则对元素进行排序。队列的头部是队列中存在时间最长的元素,而队列的尾部则是最近添加的元素。新的元素总是被插入到队列的尾部,而队列的获取操作(例如poll或peek)则是从队列头部…

Linux 中实现文本中所有的单词的第一个字符大写,其余字符小写

001、[root@PC1 test]# ls a.txt [root@PC1 test]# cat a.txt ## 测试数据 afdf eDET FDSS FFde fexk mxnd [root@PC1 test]# cat a.txt | awk {for(i = 1; i <= NF; i++) {$i = toupper(subst…

Docker方式搭建Maven私服

私服搭建 如下讲解如何基于Docker方式快速搭建Nexus3私服。 编写docker-compose.yaml文件,内容如下: version: 2services:nexus3:image: sonatype/nexus3:3.72.0container_name: nexus3restart: alwaysports:- 8081:8081 volumes:- /data/opt/nexus3/data:/nexus-data为了避免…

安全的路很长,致迷茫的你

最近有一些朋友找到我,跟我聊,说自己感觉很迷茫,不知所措,不知道未来该怎么办?安全该怎么做?OKR该怎么写?其实我想反问他以下几个问题: 1.漏洞研究了几个? 2.样本分析了几个? 3.这段时间看了多少安全技术类文档? 4.目前流行的恶意样本家族都有哪些? 5.目当流行的影…

我对什么都感兴趣,可我迷茫了

我收到一个同学给我的邮件问了个在我看来属于“太阳系”级的难题,比宇宙终极难题还差那么些^^他问: ----------------- 这几天一直挺困惑。说下我的问题,你有空的时候帮我解答下吧。 今天问自己个问题,找个自己的特长现在开始发展它。 基本上以后主要就靠这个特长工作。 但…

进程控制2

使用waitpid(pid, status,0);填入子进程的pid,阻塞父进程,直到子进程结束了,然后把子进程的pcb结构体的状态码读取出来。使用WIFEXITED(status)判断子进程是否正常退出,WEXITSTATUS(status)读取退出码来判断运行是否正常结束。 因为进程结束有3种情况:1.进程正常退出,并正…

电力煤矿液体泄漏识别系统

电力煤矿液体泄漏识别系统对电力煤矿危化品生产区域管道机械实时检测,当电力煤矿液体泄漏识别系统检测到机械管道出现液体泄漏时,系统立即抓拍存档并告警同步回传给报警信息给后台监控人员,让工作人员及时处理,电力煤矿液体泄漏识别系统实现危险区域跑冒滴漏异常自动监控抓…

河道水尺水位监测系统

河道水尺水位监测系统利用计算机视觉技术对河道湖泊水尺水位进行7*24小时全天候实时监测,当河道水尺水位监测系统监测到河道水位异常变化时,系统立即抓拍存档同步回传图片给后台监控平台,提醒后台工作人员及时处理异常情况,避免更大损失的发生。河道水尺水位监测系统适用于…