Linux 系统是个多任务操作系统,会存在多个任务同时访问同一片内存区域,这些任务可能会相互覆盖这段内存中的数据,造成内存数据混乱。我们需要对共享数据进行相应的保护处理。
产生并发的主要原因有:
①多线程并发访问, Linux 是多任务(线程)的系统,多线程访问是最基本的原因
②抢占式并发访问,Linux 内核支持抢占,调度程序可以在任意时刻抢占正在运行的线程,从而运行其他的线程。
③中断程序并发访问,硬件中断的权利可以是很大的。
④SMP(多核)核间并发访问,多核 CPU 存在核间并发访问。
并发:多个执行单元同时进行或多个执行单元微观串行执行,宏观并行执行。微观串行,宏观并行:理解成把时间轴放大以后,各个任务是串行执行,然后每个任务执行一定的时间片,执行完后由调度系统调度到另一个任务去执行。因为CPU的速度很快,所以宏观看来是并行执行。
竞争:并发的执行单元对共享资源(硬件资源和软件上的全局变量)的访问而导致的竞争状态。
临界资源: 多个进程访问的资源,共享数据段
临界区:多个进程访问的代码段
一、原子操作原子操作是指不能再进一步分割的操作。一般原子操作用于整形变量或者位操作。
Linux 内核定义了叫做 atomic_t 的结构体来完成整形数据的原子操作,在使用中用原子变量来代替整形变量,此结构体定义在 include/linux/types.h 文件中
typedef struct {
int counter;
} atomic_t;
如果要使用原子操作 API 函数,首先要先定义一个 atomic_t 的变量,
atomic_t a; //定义 a
atomic_t b = ATOMIC_INIT(0); //定义原子变量 b 并赋初值为 0
原子变量有了,接下来就是对原子变量进行操作,读、写、增加、减少。
原子操作API函数
如果使用 64 位的 SOC 的话,就使用64 位的原子变量
typedef struct {
long long counter;
} atomic64_t;
相应的操作函数把“atomic_”前缀换为“atomic64_”,将 int 换为 long long即可。
原子位操作:即位操作,在Linux 内核也提供了一系列的原子位操作 API 函数,原子位操作不像原子整形变量那样有个 atomic_t 的数据结构,原子位操作是直接对内存进行操作。
atomic_t lock; /* 原子变量 */
/* 初始化原子变量 */
atomic_set(&lock, 1); /* 原子变量初始值为1 */
atomic_inc(&lock); /*释放原子变量*/
/* 通过判断原子变量的值来检查共享资源有没有被别的应用使用:1 */
//若为1 则1-1为0 ,返回真,取反为假
//若为0 ,则0-1不为0,返回假,取反为真,执行下面
if (!atomic_dec_and_test(&gpioled.lock)) {
atomic_inc(&gpioled.lock); /* 小于0的话就加1,使其原子变量等于0 */
return -EBUSY; /* 共享资源被使用,返回忙 */
}
/* 通过判断原子变量的值来检查共享资源有没有被别的应用使用:2 */
if(atomic_read(&lock)
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?