Concurrency and competition
并发与竞态
竞态
竞态条件(race condition),从多进程间通信的角度来讲,是指两个或多个进程对共享的数据进行读或写的操作时,最终的结果取决于这些进程的执行顺序。
并发
在操作系统中,并发是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
并发管理:
竞态常是对资源的共享访问结果而产生。为了避免会发生的这种情况,在驱动设备程序中我们需要记住以下的几个规则:
1.只要可能就应该避免资源的共享,但是对于硬件资源来说,它本质上就是共享的,而软件资源经常需要对其他线程可用。
2.对于硬件资源来说,必须使用显示的管理方式。
3.当内核代码创建了一个可能和其他内核部分贡献的对象时,该对象必须在还有其他组件引用自己时保持存在。
Linux Kernel 信号量的实现
我们在”linux/semaphore.h“ 中可以看到具体的结构和基本函数,在当前4.4内核中已经作出了比2.6.x 更多的改变。
/* Please don't access any members of this structure directly */
struct semaphore { /*信号量的结构*/
raw_spinlock_t lock;
unsigned int count;
struct list_head wait_list; /*等待链表*/
};
#define __SEMAPHORE_INITIALIZER(name, n) \
{ \
.lock = __RAW_SPIN_LOCK_UNLOCKED((name).lock), \
.count = n, \
.wait_list = LIST_HEAD_INIT((name).wait_list), \
}
#define DEFINE_SEMAPHORE(name) \
struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
static inline void sema_init(struct semaphore *sem, int val) /*初始化函数*/
{
static struct lock_class_key __key;
*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
}
extern void down(struct semaphore *sem); /*减少信号量的值,调用者等待*/
extern int __must_check down_interruptible(struct semaphore *sem); /*可中断的*/
extern int __must_check down_killable(struct semaphore *sem); /*可被终结的*/
extern int __must_check down_trylock(struct semaphore *sem); /*尝试加锁,永不休眠,获取资源失败直接返回*/
extern int __must_check down_timeout(struct semaphore *sem, long jiffies); /*定时*/
extern void up(struct semaphore *sem); /*释放信号量*/
```
读取者 写入者 信号量
对于有些资源大多处于读取状态的时候,内核提供了一个读写者信号量,允许多个并发的读取者提高了性能。
```
struct rw_semaphore; /*读写信号量的结构*/
/* All arch specific implementations share the same struct */
struct rw_semaphore {
long count;
struct list_head wait_list;
raw_spinlock_t wait_lock;
struct optimistic_spin_queue osq; /* spinner MCS lock */
/*
* Write owner. Used as a speculative check to see
* if the owner is running on the cpu.
*/
struct task_struct *owner;
struct lockdep_map dep_map;
};
extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
```
初始化函数的基本操作,包括初始化的宏定义
```
#define __RWSEM_INITIALIZER(name) \
{ .count = RWSEM_UNLOCKED_VALUE, \
.wait_list = LIST_HEAD_INIT((name).wait_list), \
.wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock) \
__RWSEM_OPT_INIT(name) \
__RWSEM_DEP_MAP_INIT(name) }
#define DECLARE_RWSEM(name) \
struct rw_semaphore name = __RWSEM_INITIALIZER(name)
extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
struct lock_class_key *key);
#define init_rwsem(sem) \
do { \
static struct lock_class_key __key; \
\
__init_rwsem((sem), #sem, &__key); \
} while (0)
/*
* This is the same regardless of which rwsem implementation that is being used.
* It is just a heuristic meant to be called by somebody alreadying holding the
* rwsem to see if somebody from an incompatible type is wanting access to the
* lock.
*/
static inline int rwsem_is_contended(struct rw_semaphore *sem)
{
return !list_empty(&sem->wait_list);
}
```
读写信号量的基本操作
```
static inline int rwsem_is_contended(struct rw_semaphore *sem)
{
return !list_empty(&sem->wait_list);
}
/*
* lock for reading
*/
extern void down_read(struct rw_semaphore *sem);
/*
* trylock for reading -- returns 1 if successful, 0 if contention
*/
extern int down_read_trylock(struct rw_semaphore *sem);
/*
* lock for writing
*/
extern void down_write(struct rw_semaphore *sem);
/*
* trylock for writing -- returns 1 if successful, 0 if contention
*/
extern int down_write_trylock(struct rw_semaphore *sem);
/*
* release a read lock
*/
extern void up_read(struct rw_semaphore *sem);
/*
* release a write lock
*/
extern void up_write(struct rw_semaphore *sem);
```
一个读写信号量允许一个写入者或者无限多读取者拥有信号量,写入者拥有更高的优先级,当一个写入者在进入临界区工作的时候,直到其他的读操作完成之前是不会让读者进行操作的。
completion
这是一个允许条件唤醒阻塞的操作,我们不必面面据道这里不进行深入讨论。有一个内核模块在本章。
自旋锁
一个核心概念,自旋锁大多用于SMP结构,建议最好在短时间可控制的情况下使用自旋锁。它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。
```
static __always_inline raw_spinlock_t *spinlock_check(spinlock_t *lock)
{
return &lock->rlock;
}
#define spin_lock_init(_lock) \
do { \
spinlock_check(_lock); \
raw_spin_lock_init(&(_lock)->rlock); \
} while (0)
static __always_inline void spin_lock(spinlock_t *lock)
{
raw_spin_lock(&lock->rlock);
}
static __always_inline void spin_lock_bh(spinlock_t *lock)
{
raw_spin_lock_bh(&lock->rlock);
}
static __always_inline int spin_trylock(spinlock_t *lock)
{
return raw_spin_trylock(&lock->rlock);
}
```
Linux kernel 原子变量 与 位操作
原子变量很简单参见"include/linux/atomic.h"
```
typedef struct {
volatile int counter;
} atomic_t;
```
```
static inline int atomic_read(const atomic_t *v)
{
return v->counter;
}
static inline void atomic_set(atomic_t *v, int i)
{
v->counter = i;
}
```
### RCU 机制
这里有一个关于RCU的论文合集,由内核RCU的编写者整理,读者可自行阅读http://www2.rdrop.com/users/paulmck/RCU/
本章节有一个关于compelete 的模块,凡是读取这个模块的进程都会被阻塞,只要有写入的进程都会被唤起。
正在上传…
取消
查看原文:http://zmrlinux.com/2017/04/30/%e7%ab%9e%e6%80%81%e4%b8%8e%e5%b9%b6%e5%8f%91/
相关推荐
【Matlab 传感器布局优化】基于群智能算法的wsn覆盖优化研究
本文主要是对同构和异构传感器在指定空间内的布局进行优化,以最大覆盖率为目标,使用了DBO/SCA/WOA/SSA/NOA等启发式算法,在100x100的空间内,对30,100,200个传感器进行优化,得到最优的布局位置和对应覆盖率。
并发和竞态
1、什么是并发和竞态?? 并发:指多个执行单元同时被执行,而并发执行单元对共享资源的访问容易导致竞态(共享资源:硬件资源和软件上的全局变量、静态变量) 2、并行的例子 (1)、多个cup:使用共同的系统总线,因为可以并发访问共同的外设和储存器 (2)、单个cpu:内核支持抢占,高优先级的进程可以打断正在内核执行的低优先级的进程 (3)、中断:(硬中断、软中断、Tasklet、
A股历史数据免费下载终极指南:4000+个股数据一键打包获取
本文提供了获取A股历史数据的完整免费方案,重点介绍了Tushare Pro、AkShare等开源金融数据API的使用方法。通过详细的Python脚本示例,指导读者如何自动化批量抓取、清洗、存储4000多只个股的历史行情数据,并分享数据质量校验与性能优化技巧,助力量化研究与市场分析。
Linux内核中的竞态和并发
内联汇编 看韦东山完全开发手册中的内联汇编部分 什么是竞态 https://blog.youkuaiyun.com/lj19990824/article/details/104563968 竞态:多个执行单元同时被执行,处理的是同一个资源,就会导致竞态 导致竞态原因: 1.多进程同时访问操作临界资源(进程和抢占它的进程之间会导致竞态) 2.进程和中断 3.对称多处理器 解决竞态的具体方法 1.屏蔽中断 2.原子变量 3.使用锁 什么是抢占? 一个线程在一个cpu上运行, 不是这个线程主动让出cpu导致的其
生产实习-实习报告-Raspberry Pi的应用
生产实习-Raspberry Pi的应用 一.设计任务: 1、搭建树莓派开发环境 主要包括烧录树莓派操作系统,远程访问树莓派,树莓派接口配置以及树莓派与windows实现文件共享等。 2、树莓派的基本操作 控制GPIO点亮LED灯以及树莓派舵机云台控制 3、安装OpenCV及图像采集实验 OpenCV配合树莓派,直接读取来自树莓派摄像头Pi Camera的视频,进行人脸识别、边缘检测、颜色判别等各种计算机视觉开发。 4、树莓派小车远程Wi-Fi控制 使用树莓派驱动L298N,用树莓派板载Wi-Fi控制
UE5.3.2 + VS2022社区版在Win11上的C++编译环境配置全解
Unreal Engine 5的C++开发依赖严格的工具链协同,其核心在于Visual Studio编译器版本、Windows SDK与引擎构建系统(UBT)的精准匹配。UE5.3.2强制要求MSVC v143.4(即VS2022 17.4+)及Windows 11 SDK 10.0.22621.0,任何偏差都会引发LNK2019链接失败、C1083头文件缺失或MSB8066构建中断等典型错误。该配置不仅关乎安装顺序,更涉及注册表清理、PATH环境变量、SDK路径注入与运行时DLL加载等底层机制。适用于Wi
rw_semaphore 原理与代码分析
linux 5.10版本 读写信号量 rw_semaphore 原理分析
基于深度学习方法(7种)的高光谱与多光谱图像融合(附代码+3个数据集获取)
其他不懂的可以把代码发给AI哦,让它给你解读。
并发与竞态
同步异步的区别: 同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。 而我们平时经常讨论的同步问题多发生在多线程环境中的数据共享问题。即当多个线程需
04 Zabbix自定义触发器
1、触发器是什么 触发器表达式:允许定义一个什么状况的数据是“可接受”的阈值。因此,如果接收的数据超过了可接受的状态,则触发器会被触发 , 或将状态更改为异常。 一个触发器可以拥有下面几种状态: 值 描述 OK 这是一个正常的触发器状态。在旧版本的Zabbix中称为FALSE。 PROBLEM 通常意味着发生了某些事情。例如,处理器的负载较高。在旧版本的Zabbix中称为TRUE。 2、创建触发器TRIGGER 案例:系统超过3个用户登录,则告警。 2.1 开启告警声
Python 爬虫实战:社交媒体(Facebook)评论数据抓取与情感分析
在当今数字化时代,社交媒体平台如 Facebook 已成为人们日常生活中不可或缺的一部分。它不仅是人们分享生活点滴、交流思想的场所,也为企业和研究人员提供了丰富的数据资源。通过分析社交媒体上的评论数据,我们可以了解用户的情感倾向、产品反馈以及社会热点话题等。本文将详细介绍如何使用 Python 爬虫技术抓取 Facebook 上的评论数据,并进行情感分析。这不仅是一次技术实战,更是一次数据探索之旅。
16 并发和竞态
linux内核的并发和竞态
YOLO26科研升级:OREPA在线重参数化,让模型精度在训练中持续跃升
在目录下,新建AddModules文件夹,将orepa.py放入其中。
Linux内核并发和竞态
要求LED设备只能被一个应用程序打开访问操作。
jre9下载 jdk9
(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】
最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版
Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。
并发-竞态条件
本文所整理的知识点源自于 (Java 并发编程实战) 一书,有兴趣的童鞋可以去网上下载或者在评论区里向博主讨要。 在并发编程中,由于不恰当的执行程序而出现不正确的结果是一种非常重要的情况,它的名字叫:竞态条件(RaceCondition). 在UnsafeCountingFactorizer中存在多个竞态条件,从而使结果变得不可靠。当某个正确性取决于多个线程的交替执行时序时,...
VC中sqlite的使用
在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示
并发与竞态控制
并发控制与竞态: 并发是指多个单元同时、并行被执行,而并发执行单元对共享资源的访问 很容易导致竞态。 竞态的解释: 假设有一个设备,执行单元A对其写入3000个字符'a'而另一个执行单元B对 其写入4000个'b',第三个执行单元C读取globalmem的所有字符,如果执行单元A 、B对于设备的写入操作同时发生,此时就会造成竞态 竞态状态的分类 :
Camera2Demo
在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作
Linux驱动之并发与竞态
并发控制与竞态: 并发是指多个单元同时、并行被执行,而并发执行单元对共享资源的访问 很容易导致竞态。 竞态的解释: 假设有一个设备,执行单元A对其写入3000个字符'a'而另一个执行单元B对 其写入4000个'b',第三个执行单元C读取globalmem的所有字符,如果执行单元A 、B对于设备的写入操作同时发生,此时就会造成竞态 竞争状态的分类:
漫画 | Linux 并发和竞态问题究竟是什么?
作者 |写代码的篮球球痴责编| 郭芮学习Linux的时候,肯定会遇到各种和锁相关的知识,有时候自己学好了一点,感觉半桶水的自己已经可以华山论剑了,又突然冒出一个新的知...
linux内核的并发与竞态的理解
一、概念理解 1.概述 对于我们的驱动程序,或一个代码片段,是可以被两个独立的进程同时执行。驱动程序,或者代码片段对cpu来说就是机器指令,显然指令是可以同时发出的。但是共享资源却不能同时使用,不然就没法统计了。 2.竞态 多个进程同时执行某一代码段,或者调用同一个驱动程序;而这一代码段涉及到对内存的分配,或者驱动程序对硬件进行访问;由于内存或者硬件资源对系统来说都是共享的,那么就容易出问题。比如...
并发与竞态及解决途径
并发与竞态及解决途径 并发(concurrency)是指多个执行单元同时、并行的被执行,而并发执行单元对共享资源的访问很容导致竞态(race condition)。 并发与竞态发生的条件:对称多处理器(SMP)的多个CPU;单CPU内进程与抢占它的进程;中断与进程之间。 解决并发与竞态的途径 访问共享资源的代码区域称为临界区域(critical section),解决竞态的根本途径就是
linux并发和竞态2
SMP(对称多处理器), 中断, 强占式内核(多进程)并发导致的竞态.竞态通常是对共享资源的访问产生的, 因此驱动程序中要尽可能避免产生共享数据.最明显的,避免在驱动中使用全局变量全局变量不是共享数据的唯一途径, 只要我们的代码把一个指针传递给了内核的其他部分, 一个共享数据可能就会产生.解决共享的一个方式是"加锁".或者"互斥".1. 原子变量普通变量读改写三步导致访问一个基础变量也会有并发问题内核提供原子变量并使用专用访问的函数实现读。
Linux驱动中的并发和竞态
在 Linux 驱动开发中,并发(Concurrency)和竞态(Race Condition)是必须处理的核心问题。当多个执行路径(进程、线程、中断等)同时访问共享资源时,若缺乏同 代码传至并发竞态控制 并发进程 导致竞态的一个例子 前面所述的字符驱动都是没有考虑并发竟态的情况,想象一下 一个进程去读一个字符设备,另一个进程在同一时间向这个设备写入(完全有这种情况) 原来设备中存有 A B C D 要想设备写入1 2 3 4 每次读写一个字节 t1 t2 t3 t4 t5 t
第5章:并发与竞态条件-0:并发与竞态条件
本文讨论了Linux内核中字符设备驱动的并发问题与竞态条件。早期Linux内核并发源较少,仅通过硬件中断处理实现并发,而现代内核支持多处理器系统,大大提高了并发复杂度。作者以scull驱动为例,分析了两个进程同时写入同一内存区域时可能产生的竞态条件:后执行的进程会覆盖前者的内存分配,导致内存泄漏。这种并发漏洞不仅可能引发性能问题,还可能导致系统崩溃或数据损坏。文章强调,虽然竞态条件看似发生概率低,但在高并发环境下可能频繁出现,因此驱动程序必须从一开始就考虑并发管理。
linux 竞态与并发编程
前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、并发与竞态 并发(concurrency) 指的是多个执行单元同时、并行被执行,而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量等)的访问则很容易导致竞态(race conditions)。 例如,对于globalmem设备,假设一个执行单元A对其写入3000个字符“a”
1818



被折叠的 条评论
为什么被折叠?



