522|0

73

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

《原子Linux驱动开发》5-并发与竞争 [复制链接]

阅读章节并发:第8章:并发与竞争实验

1并发与竞争

跟上一节一样,原子哥这一期先给我们把思想讲明白,这样再理解起来像进程的并发竞争这种抽象的概念,理解起来会非常容易。并发就是多个“用户”同时访问同一个共享资源,比如你们公司有一台打印机,你们公司的所有人都可以使用。现在小李和小王要同时使用这一台打印机,都要打印一份文件。这两份文档肯定是各自打印出来的,不能相互影响。当两个人同时打印的话如果打印机不做处理的话可能会出现小李的文档打印了一行,然后开始打印小王的文档,这样打印出来的文档就错乱了。
可以想到,小王打印出来的文档中电话号码错误了,变成小李的了,这是绝对不允许的。如果有多人同时向打印机发送了多份文档,打印机必须保证一次只能打印一份文档,只有打印完成以
后才能打印其他的文档。
并发访问带来的问题就是竞争,学过FreeRTOS的同学应该知道临界区这个概念
我们一般在编写驱动的时候就要考虑到并发与竞争,而不是驱动都编写完了然后再处理并发与竞争。
C 语言里面简简单单的一句“a=3”,编译成汇编文件以后变成了 3 句,那么程序在执行的时候肯定是按照示例代码 47.2.1.1 中的汇编语句一条一条的执行。假设现在线程 A要向 a 变量写入 10 这个值,而线程 B 也要向 a 变量写入 20 这个值,我们理想中的执行顺序如图 所示:

按照图 所示的流程,确实可以实现线程 A 将 a 变量设置为 10,线程 B 将 a 变量设置为 20。但是实际上的执行流程可能如图 所示:

线程 A 最终将变量 a 设置为了 20,而并不是要求的 10!线程B 没有问题。这就是一个最简单的设置变量值的并发与竞争的例子,要解决这个问题就要保证示例代码 中的三行汇编指令作为一个整体运行,也就是作为一个原子存在。
2自旋锁

当一个线程要访问某个共享资源的时候首先要先获取相应的锁, 锁只能被一个线程持有,只要此线程不释放持有的锁,那么其他的线程就不能获取此锁。对于自旋锁而言,如果自旋锁正在被线程 A 持有,线程 B 想要获取自旋锁,那么线程 B 就会处于忙循环-旋转-等待状态,线程 B 不会进入休眠状态或者说去做其他的处理,而是会一直傻傻的在那里“转圈圈”的等待锁可用。比如现在有个公用电话亭,一次肯定只能进去一个人打电话,现在电话亭里面有人正在打电话,相当于获得了自旋锁。此时你到了电话亭门口,因为里面有人,所以你不能进去打电
话,相当于没有获取自旋锁,这个时候你肯定是站在原地等待,你可能因为无聊的等待而转圈圈消遣时光,反正就是哪里也不能去,要一直等到里面的人打完电话出来。终于,里面的人打
完电话出来了,相当于释放了自旋锁,这个时候你就可以使用电话亭打电话了,相当于获取到了自旋锁。
自旋锁的“自旋”也就是“原地打转”的意思,“原地打转”的目的是为了等待自旋锁可以用,可以访问共享资源。把自旋锁比作一个变量 a,变量 a=1 的时候表示共享资源可用,当 a=0的时候表示共享资源不可用。现在线程 A 要访问共享资源,发现 a=0(自旋锁被其他线程持有),那么线程 A 就会不断的查询 a 的值,直到 a=1。从这里我们可以看到自旋锁的一个缺点:那就等待自旋锁的线程会一直处于自旋状态,这样会浪费处理器时间,降低系统性能,所以自旋锁的持有时间不能太长。所以自旋锁适用于短时期的轻量级加锁,如果遇到需要长时间持有锁的场景那就需要换其他的方法了,
3信号量

大家如果有学习过 FreeRTOS的话就应该对信号量很熟悉,因为信号量是同步的一种方式。 Linux 内核也提供了信号量机制,信号量常常用于控制对共享资源的访问。举一个很常见的例子,某个停车场有 100 个停车位,这 100 个停车位大家都可以用,对于大家来说这100 个停车位就是共享资源。假设现在这个停车场正常运行,你要把车停到这个这个停车场肯定要先看一下现在停了多少车了?还有没有停车位?当前停车数量就是一个信号量,具体的停车数量就是这个信号量值,当这个值到 100 的时候说明停车场满了。停车场满的时你可以等一会看看有没有其他的车开出停车场,当有车开出停车场的时候停车数量就会减一,也就是说信号量减一,此时你就可以把车停进去了,你把车停进去以后停车数量就会加一,也就是信号量加一。这就是一个典型的使用信号量进行共享资源管理的案例,在这个案例中使用的就是计数型信号量。
相比于自旋锁,信号量可以使线程进入休眠状态,比如 A 与 B、 C 合租了一套房子,这个房子只有一个厕所,一次只能一个人使用。某一天早上 A 去上厕所了,过了一会 B 也想用厕所,因为 A 在厕所里面,所以 B 只能等到 A 用来了才能进去。 B 要么就一直在厕所门口等着,等 A 出来,这个时候就相当于自旋锁。 B 也可以告诉 A,让 A 出来以后通知他一下,然后 B 继续回房间睡觉,这个时候相当于信号量。可以看出,使用信号量会提高处理器的使用效率,毕竟不用一直傻乎乎的在那里“自旋”等待。但是,信号量的开销要比自旋锁大,因为信号量使线程进入休眠状态以后会切换线程,切换线程就会有开销。
4总结

在Linux系统中,并发是指系统能够同时处理多个任务的能力,这些任务可以是同时运行的进程或线程。Linux系统是一个多任务操作系统,可以同时运行多个进程,并发是其设计的核心特性之一。

竞争是指多个进程或线程试图同时访问共享资源(如内存、文件、网络连接等)时所发生的现象。在竞争的情况下,如果不加以处理,可能会导致数据不一致、死锁等问题。

在Linux中,处理并发和竞争的一些常见机制和工具包括:

  1. 进程和线程:Linux系统支持多进程和多线程,可以通过创建多个进程或线程来实现并发处理。

  2. 进程间通信(IPC):Linux提供了多种IPC机制,如管道、消息队列、共享内存等,用于不同进程之间的通信和数据共享。

  3. 信号量和互斥量:Linux提供了信号量和互斥量等同步机制,用于控制多个进程或线程对共享资源的访问。

  4. 文件锁:Linux提供了文件锁机制,可以通过fcntl系统调用对文件进行加锁,防止多个进程同时对同一文件进行读写操作。

  5. 读写锁:Linux提供了读写锁机制,允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。

  6. 信号处理:Linux系统使用信号来处理异步事件,可以通过信号处理函数来处理并发情况下的异常情况。

通过合理地使用这些机制和工具,可以有效地处理Linux系统中的并发和竞争,确保系统的稳定性和可靠性。

本书除了本文中提到的所有思想外,对每个概率也有具体的代码说明,结合代码会使我们有更真切的理解,不得不说,原子哥可谓是费劲心思想让读者明白,不过确实也做到了,点赞

 

点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表