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

windows内核研究(驱动开发-多核同步之临界区和自旋锁)

驱动开发


多核同步之临界区

并发和同步:

  • 并发是指多个线程在同时执行
    • 单核(是分时执行,不是真正的同时)
    • 多核(在某一时刻,会同时有多个线程在执行)
  • 同步则是保证在并发执行的环境中各个线程可以有序的执行
// 在多线程中改变全局变量int g_num = 0;// Thread代码
void add(){g_num++; // 线程不安全
}

从汇编的角度看

在上面的thread线程代码块中看似代码只有一行:g_num++
但是在汇编代码中是有三行对应的汇编指令

// 编译后的汇编
1.mov eax,[g_num]
2.add eax,1
3.mov [g_num],eax// 在执行多线程代码时,先执行了第一行和第二行汇编代码
// 这里发生了CPU线程切换(可能是主动切换,也可能是被动切换比如CPU时间片到时)
// 这样以来第一行和第二行代码分别被执行了两次,但最后的结果却只加了一次

我们再看另一条汇编代码

inc dword ptr ds:[g_num] 	// 这时再执行之前的线程代码还安全吗?

先说结论:

  1. 如果当前CPU是单核的,那么这条指令就是安全的(单核CPU不会出现两个CPU同时执行一条指令的情况,要么执行完,要么还没执行 )
  2. 如果当前CPU是多核的,那么这条指令就是不安全的(多核CPU会出现两个CPU执行同一条指令的情况,导致最后的执行结果不符合预期)
lock inc dword ptr ds:[g_num] // 改为以下指令后,即使在多核CPU下执行也不会发生线程安全的问题

lock 指令锁当前操作的地址

先读的线程先锁住,后执行的线程在前一个线程执行完后,再继续上锁执行,这样以来在多核CPU下也不会出现线程安全的问题

windows为我们提供的线程安全的API

InterlockedIncrement // 原子地增加一个32位/64位整数
InterlockedDecrement // 原子地减少一个32位/64位整数
InterlockedExchange // 原子交换一个变量的值,并返回旧值
InterlockedCompareExchange // 原子比较并交换,并返回原始值
InterlockedExchangeAdd // 原子地加上一个值,并返回原始值
InterlockedFlushSlist // 原子地清空链表,并返回所有节点
InterlockedPopEntrySList // 原子地弹出 链表头节点
InterlockedPushEntrySList // 原子地插入一个节点到链表头部

windows是如何实现多核线程安全的InterIockedIncrement函数分析:

在这里插入图片描述
多行代码的原子操作

lock只能锁住一行指令,无法锁住多行

windwos使用临界区的概念来达到一次只允许一个线程进入直到离开

// 全局变量: flag = 0进入临界区:
Lab:mov eax,1lock xadd[flag],eaxcmp eax,0jz endLab:dec [flag]// 线程等待jpm Lab
endLab:call A() // 执行方法call A():mov esp,ebpsub 1c...
离开临界区:lock dec [flag]	

多核同步之自旋锁

在多核windows系统下,ntoskrnl.exe模块的代码才会加锁进行判断

SwapContext线程切换函数中的关键上锁位置
在这里插入图片描述
在单核中也有这个函数,只不过什么都不做为了兼容

在这里插入图片描述
总结:

  • 自旋锁只对多核有意义
  • 自旋锁与临界区,事件,互斥体一样,都是一种同步机制,都可以让当前线程处于等待状态,区别在于自旋锁不用切换线程,性能更好
http://www.lryc.cn/news/594971.html

相关文章:

  • 【Linux内核】Linux驱动开发
  • 智慧场景:定制开发开源AI智能名片S2B2C商城小程序赋能零售新体验
  • 莘默曹工-Cd Automation半导体调功器 RS2300-
  • Mac安装Typescript报错
  • 电脑声音修复?【图文详解】电脑没有声音?声音异常
  • 如何升级到macOS Tahoe:全面指南与实用步骤
  • node.js 为什么要装 express组件
  • Node.js的Transform 流
  • 深度学习-常用环境配置
  • Spring 对数组和集合类的自动注入
  • 机器学习初学者理论初解
  • Oracle 数据库共享池与大池调优指南
  • ElasticSearch:不停机更新索引类型(未验证)
  • Django基础(五)———模板结构
  • 中小型企业如何选择合适的WMS系统?
  • 如何用DispatcherTimer提高运行总时间的精确度
  • AI探索 | 基于 Node.js 开发 MCP 客户端+服务端及优秀项目分享
  • Node.js- node管理工具nvm
  • Spring @RequestBody注解详解与实践
  • Dockerfile 完全指南:从入门到精通
  • 西门子 S7-1500 信号模块硬件配置全解析:从选型到实战
  • (10)机器学习小白入门 YOLOv:YOLOv8-cls 模型评估实操
  • 使用 Tailwind CSS 控制元素在移动端不显示
  • 【LuckiBit】macOS/Linux 常用命令大全
  • Jenkins pipeline触发下游流水线
  • 用Java 代码实现一个简单的负载均衡逻辑
  • 2025最新版PyCharm for Mac统一版安装使用指南
  • springcloud -- 微服务02
  • 【Unity优化】Unity多场景加载优化与资源释放完整指南:解决Additive加载卡顿、预热、卸载与内存释放问题
  • 【c++】leetcode438 找到字符串中所有字母异位词