当前位置: 首页 > news >正文

Linux内核并发与竞争-原子操作

一.原子操作的概念

首先看一下原子操作,原子操作就是指不能再进一步分割的操作,一般原子操作用于变量或者位操作。假如现在要对无符号整形变量 a 赋值,值为 3,对于 C 语言来讲很简单,直接就是: a=3

但是 C 语言要先编译为成汇编指令, ARM 架构不支持直接对寄存器进行读写操作,比如要借助寄存器 R0、 R1 等来完成赋值操作。假设变量 a 的地址为 0X3000000,“a=3”这一行 C语言可能会被编译为如下所示的汇编代码:

ldr r0, =0X30000000 /* 变量 a 地址 */

ldr r1, = 3 /* 要写入的值 */

str r1, [r0] /* 将 3 写入到 a 变量中 */

示例代码 只是一个简单的举例说明,实际的结果要比示例代码复杂的多。从上述代码可以看出, C 语言里面简简单单的一句“a=3”,编译成汇编文件以后变成了 3 句,那么程序在执行的时候肯定是按照示例代码 中的汇编语句一条一条的执行。假设现在线程 A要向 a 变量写入 10 这个值,而线程 B 也要向 a 变量写入 20 这个值,我们理想中的执行顺序如图 所示:

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

按照图 所示的流程,线程 A 最终将变量 a 设置为了 20,而并不是要求的 10!线程B 没有问题。这就是一个最简单的设置变量值的并发与竞争的例子,要解决这个问题就要保证示例代码 中的三行汇编指令作为一个整体运行,也就是作为一个原子存在。 Linux 内核提供了一组原子操作 API 函数来完成此功能, Linux 内核提供了两组原子操作 API 函数,一组是对整形变量进行操作的,一组是对位进行操作的,我们接下来看一下这些 API 函数。

二.原子操作的函数介绍

1.原子整形操作API函数

Linux 内核定义了叫做 atomic_t 的结构体来完成整形数据的原子操作,在使用中用原子变量来代替整形变量,此结构体定义在 include/linux/types.h 文件中,定义如下:

typedef struct {int counter;
} atomic_t;

2.原子位操作API函数

三.实验

我们这个还是之前的思路,如果不牵扯到硬件操作,那么我们就在ubuntu pc做实验,这样高效,比较方便

driver

#include <linux/types.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/device.h>#define CHRDEVBASE_MAJOR    200
uint8_t kernel_buffer[1024] = {0};
static struct class *hello_class;
atomic_t lock;static int hello_world_open(struct inode * inode, struct file * file)
{int count;printk("hello_world_open\r\n");count = atomic_read(&lock);printk("count:%d\r\n",count);if(count){printk("already open ,return fail\r\n");}elseatomic_inc(&lock);return 0;
}static int hello_world_release (struct inode * inode, struct file * file)
{printk("hello_world_release\r\n");atomic_dec(&lock);return 0;
}static const struct file_operations hello_world_fops = {.owner        = THIS_MODULE,.open        = hello_world_open,.release = hello_world_release,.read        = NULL,.write    = NULL,
};static int __init hello_driver_init(void)
{int ret;printk("hello_driver_init\r\n");atomic_set(&lock,0);ret = register_chrdev(CHRDEVBASE_MAJOR,"hello_driver",&hello_world_fops);hello_class = class_create(THIS_MODULE,"hello_class");device_create(hello_class,NULL,MKDEV(CHRDEVBASE_MAJOR,0),NULL,"hello"); /* /dev/hello */return 0;
}static void __exit hello_driver_cleanup(void)
{printk("hello_driver_cleanup\r\n");device_destroy(hello_class,MKDEV(CHRDEVBASE_MAJOR,0));class_destroy(hello_class);unregister_chrdev(CHRDEVBASE_MAJOR,"hello_driver");}module_init(hello_driver_init);
module_exit(hello_driver_cleanup);
MODULE_LICENSE("GPL");

app

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>/* mknod /dev/chrdevbase c 200 0 */uint8_t buffer[512] = {0};int main(int argc, char *argv[])
{int fd;int ret;fd  = open(argv[1], O_RDWR);printf("sleep\r\n");sleep(60);printf("wake up\r\n");close(fd);}

Makefile

KERNELDIR := /lib/modules/$(shell uname -r)/build
CURRENT_PATH := $(shell pwd)
obj-m := atomic_driver.obuild: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules$(CROSS_COMPILE)gcc -o test_app test_app.c
clean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) cleanrm -rf test_app

参考:

1.【韦东山】嵌入式Linux应用开发完全手册V4.0_韦东山全系列视频文档-IMX6ULL开发板.docx

2.【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.4.pdf

相关文章:

Linux内核并发与竞争-原子操作

一.原子操作的概念首先看一下原子操作&#xff0c;原子操作就是指不能再进一步分割的操作&#xff0c;一般原子操作用于变量或者位操作。假如现在要对无符号整形变量 a 赋值&#xff0c;值为 3&#xff0c;对于 C 语言来讲很简单&#xff0c;直接就是&#xff1a; a3但是 C 语言…...

Java笔记-泛型的使用

参考&#xff1a; Java 泛型&#xff0c;你了解类型擦除吗&#xff1f; 泛型的使用 1、泛型的定义 可以广泛使用的类型&#xff0c;一种较为准确的说法就是为了参数化类型&#xff0c;或者说可以将类型当作参数传递给一个类或者是方法。 2、泛型的使用 2.1泛型类 public c…...

特斯拉无人驾驶解读

来源于Tesla AI Day Tesla无人驾驶算法的核心任务就是如何理解我们所看到的一切呢?也就是说,不使用高端的设备,比如激光雷达,仅仅使用摄像头就能够将任务做得很好。Tesla使用环绕型的8个摄像头获得输入。 第一步是特征提取模块Backbone,无论什么任务都离不开特征…...

生物素-琥珀酰亚胺酯Biotin-NHS;CAS号:35013-72-0;可对溶液中的抗体,蛋白质和任何其他含伯胺的大分子进行简单有效的生物素标记。

结构式&#xff1a; ​ 生物素-琥珀酰亚胺酯Biotin NHS CAS号&#xff1a;35013-72-0 英文名称&#xff1a;Biotin-NHS 中文名称&#xff1a;D-生物素 N-羟基琥珀酰亚胺酯&#xff1b;生物素&#xff0d;琥珀酰亚胺酯 CAS号&#xff1a;35013-72-0 密度&#xff1a;1.50.1 …...

Maven_第五章 核心概念

目录第五章 其他核心概念1、生命周期①作用②三个生命周期③特点2、插件和目标①插件②目标3、仓库第五章 其他核心概念 1、生命周期 ①作用 为了让构建过程自动化完成&#xff0c;Maven 设定了三个生命周期&#xff0c;生命周期中的每一个环节对应构建过程中的一个操作。 …...

【深度学习】人脸识别工程化落地

文章目录前言1、facenet2、使用2.1.其它blog2.2 实践总结前言 老早以前就希望能写一篇关于人脸识别的工程化落地的案例&#xff0c;一年前做疲劳驾驶时使用的dlib插件&#xff0c;它封装好了&#xff0c;人脸检测、对齐、相似度计算三个部分,就是插件比较难装,但同时也少了很多…...

AOP面向切面编程思想。

目录 一、AOP工作流程 1、基本概念 2、AOP工作流程 二、AOP核心配置 1、AOP切入点表达式 2、AOP通知类型 三、AOP通知获取数据 1、获取参数 2、获取返回值 3、获取异常 四、AOP事务管理 1、Spring事务简介 2、Spring事务角色 3、事务属性 一、AOP工作流程 1、…...

实验7-变治技术及动态规划初步

目录 1.统计个数 2.数塔dp -A 3.Horspool算法 4.计数排序 5.找零问题1-最少硬币 1.统计个数 【问题描述】有n个数、每个元素取值在1到9之间,试统计每个数的个数 【输入形式】第一行,n的值;第二行࿰...

JVM垃圾回收机制GC理解

目录JVM垃圾回收分代收集如何识别垃圾引用计数法可达性分析法引用关系四种类型&#xff1a; 强、软、弱、虚强引用软引用 SoftReference弱引用 WeakReferenceWeakHashMap软引用与虚引用的使用场景虚引用与引用队列引用队列虚引用 PhantomReference垃圾回收算法引用计数复制 Cop…...

C++中的容器

1.1 线性容器1&#xff09;std::array看到这个容器的时候肯定会出现这样的问题&#xff1a;为什么要引入 std::array 而不是直接使用 std::vector&#xff1f;已经有了传统数组&#xff0c;为什么要用 std::array?先回答第一个问题&#xff0c;与 std::vector 不同&#xff0c…...

2023备战金三银四,Python自动化软件测试面试宝典合集(五)

接上篇八、抓包与网络协议8.1 抓包工具怎么用 我原来的公司对于抓包这块&#xff0c;在 App 的测试用得比较多。我们会使用 fiddler 抓取数据检查结果&#xff0c;定位问题&#xff0c;测试安全&#xff0c;制造弱网环境;如&#xff1a;抓取数据通过查看请求数据&#xff0c;请…...

SpringDI自动装配BeanSpring注解配置和Java配置类

依赖注入 上篇博客已经提到了DI注入方式的构造器注入&#xff0c;下面采用set方式进行注入 基于set方法注入 public class User {private String name;private Address address;private String[] books;private List<String> hobbys;private Map<String,String>…...

2月面经:真可惜...拿了小米的offer,字节却惨挂在三面

我是2月份参加字节跳动和华为的面试的&#xff0c;虽然我只拿下了小米的offer&#xff0c;但是我自己也满足了&#xff0c;想把经验分享出来&#xff0c;进而帮助更多跟我一样想进大厂的同行朋友们&#xff0c;希望大家可以拿到理想offer。 自我介绍 我是16年从南京工业大学毕…...

磐云PY-B8 网页注入

文章目录1.使用渗透机场景windows7中火狐浏览器访问服务器场景中的get.php&#xff0c;根据页面回显获取Flag并提交&#xff1b;2.使用渗透机场景windows7中火狐浏览器访问服务器场景中的post.php&#xff0c;根据页面回显获取Flag并提交&#xff1b;3.使用渗透机场景windows7中…...

多传感器融合定位十-基于滤波的融合方法Ⅰ其二

多传感器融合定位十-基于滤波的融合方法Ⅰ其二3. 滤波器基本原理3.1 状态估计模型3.2 贝叶斯滤波3.3 卡尔曼滤波(KF)推导3.4 扩展卡尔曼滤波(EKF)推导3.5 迭代扩展卡尔曼滤波(IEKF)推导4. 基于滤波器的融合4.1 状态方程4.2 观测方程4.3 构建滤波器4.4 Kalman 滤波实际使用流程4…...

Java集合面试题:HashMap源码分析

文章目录一、HashMap源码二、HashMap数据结构模型图三、HashMap中如何确定元素位置四、关于equals与hashCode函数的重写五、阅读源码基本属性参考文章&#xff1a;史上最详细的 JDK 1.8 HashMap 源码解析参考文章&#xff1a;Hash详解参考文章&#xff1a;hashCode源码分析参考…...

华为OD机试 - 数组合并(Python),真题含思路

数组合并 题目 现在有多组整数数组, 需要将他们合并成一个新的数组。 合并规则, 从每个数组里按顺序取出固定长度的内容合并到新的数组中, 取完的内容会删除掉, 如果该行不足固定长度或者已经为空, 则直接取出剩余部分的内容放到新的数组中, 继续下一行。 如样例 1, 获得长度…...

Vue2创建移动端项目

一、Vscode Vscode 下载安装以及常用的插件 1、Vscode 下载 下载地址&#xff1a;Vscode 中文语言插件 搜索 chinese 主题 Atom 主题 文件图标主题 搜索 icon 源代码管理插件GitLens 搜索 GitLens Live Server _本地服务器 搜索 Live Server Prettier - Code formatt…...

PorterDuffXfermode与圆角图片

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 圆角图片 在项目开发中&#xff0c;我们常用到这样的功能&#xff1a;显示圆角图片。 这个是咋做的呢&#xff1f;我们来瞅瞅其中一种实现方式 /*** param bitmap 原图* p…...

如何准备大学生电子设计竞赛

大学生电子设计竞赛难度中上&#xff0c;一般有好几个类型题目可以选择&#xff0c;参赛者可以根据自己团队的能力、优势去选择合适自己的题目&#xff0c;灵活自主空间较大。参赛的同学们可以在暑假好好学习相关内容&#xff0c;把往年的题目拿来练练手。这个比赛含金量还是有…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...