内核并发消杀器(KCSAN)技术分析
一、KCSAN介绍
KCSAN(Kernel Concurrency Sanitizer)是一种动态竞态检测器,它依赖于编译时插装,并使用基于观察点的采样方法来检测竞态,其主要目的是检测数据竞争。
KCSAN是一种检测LKMM(Linux内核内存一致性模型)定义的数据竞争(data race)的工具,同时它也可以控制报告哪种类型的数据竞争。
KCSAN知道LKMM定义的所有标记原子操作,以及LKMM尚未提到的操作,例如原子位掩码操作(bit mask)。
KCSAN扩展了LKMM,例如通过提供data_race()标记,来表示存在数据竞争和缺乏原子可能性。
1.1 LKMM(Linux内核内存一致性模型)
Linux内核内存模型目前在源代码树中的memory-barrier.txt和atomic_ops.txt文件中有非正式的定义。包含以下组成部分:
变量访问(Variable Access)
使用READ_ONCE()、WRITE_ONCE()和ACCESS_ONCE()宏来保护从共享(但非原子)变量的加载和存储;
内存屏障(Memory Barriers)
一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作。比如barrier、smp_mb/smp_wmb/smp_rmb等;
锁操作(Locking Operations)
原子操作(Atomic Operations)
控制依赖(Control Dependencies)
Linux内核提供了一个有限的控件依赖的概念,在某些情况下对依赖控件的存储进行优先加载;
RCU宽限期授权关系(Grace-Period Relationships)
允许更新者等待所有已经存在的读侧临界区完成,再回收旧的资源;
C11原子原语 (C11 Atomics)
将原子原语的实现委托给编译器;如果多个体系结构采用这种方法,将减少体系结构特定代码的数量。
1.2 数据竞争
为什么要关心数据竞争?
C语言的发展独立于并发性。如果给定的变量或访问没有任何特别之处,则变量只会在响应当前线程的存储时发生变化。
C语言和编译器的进化对并发性不敏感
优化编译器正变得越来越丰富
因此,编译器可以并且使用各种优化,包括负载融合、代码重新排序和许多其他可能导致并发算法故障的优化。
读取拆分(单次访问多次读取)
存储拆分(单次访问多次写入)读取融合(编译器直接使用上一次对这个变量的load结果,而不是真正再去load一次)
存储融合(编译器优化写入变量流程,不再真实写入)
代码重排(把一些类似的计算归在一起,节省占用的寄存器,改善现代超标量微处理器里面各个运算单元的利用效率)
虚拟读取(编译器优化会导致多次读取,导致后续加载异常)
虚拟存储(编译器优化会导致多次存储,导致后续存储异常)
.....
因此需要告诉编译器并发代码,Linux提供内存一致性模型,也提供检查方法解决此类问题。
1.2.1 访问方式
普通访问
标记访问

1.2.2 同步冲突访问的检测条件
在访问同一个地方并且至少有一个是写操作
至少有一个是普通访问(比如x+42)
以下线程打钩的是标准做法;打叉的是可能存在数据竞争的情况。

1.2.3 哪些不属于数据竞争
例如:使用不对称的锁机制,并且使用READ_ONCE/WRITE_ONCE标记访问。

二、依赖与配置方案
2.1 版本支持
KCSAN支持GCC/CLANG编译,需要GCC版本11,CLANG 12以上版本。
x86_64: >=5.8 ARM64: >=5.17


2.2 KCSAN工具链支持
cc-option,-fsanitize=thread --param tsan-distinguish-volatile=1

2.3 配置选项支持

三、工作原理与触发条件
3.1 使用方式
检查未标记读取是否写入竞争,会持续扫描内核的主要分支,在访问的内存位置上设置观察点,挑出导致数据争用的数据,并将其报告给内核日志。
●用“软观察点”查找竞争
〇设置观察点和失速通道;
〇如果监测点已经存在,那么竞争检查将照常进行;
〇如果值改变了--> 竞争;
〇失速通道随机延迟,增加观察竞争状态的机会;
默认值:任务[1,80]us,中断[1,20]us。
●为所有检测内存访问设置观察点
〇 注释标记访问,仅用于检查非标记访问是否存在观察点;
KCSAN从不在标记的访问上设置观察点;
如果对并发访问的变量的所有访问都正确地标记了,KCSAN将永远不会触发观察点,因此永远不会报告访问。
●采样: 周期性建立观察点
〇默认值:平均2000次访问。
3.2 KCSAN软观测点
基于地址页索引
〇可以溢出到相邻槽。
〇使用索引确保报告元数据给匹配的生产者/消费者。
具有灵活、可缩放的特点,以数组的形式存放。

代码片段如下:
入口函数check_access,在check_access数据地址、长度、类型;在check_access函数执行find_watchpoint判断。需要检测的ptr已经插桩编译。

3.3 KCSAN 运行流程
进入check_access函数,格式描述包含数据指针、长度、读写类型;
确认是否需要观测,需要满足至少一个写操作且为普通访问;
如果判定需要观测,加入观察列表;
延时一段时长,查看是否有访问、变更数据等情况;如果有,则生产数据表,并打印数据到控制台;如果没有则退出;
在步骤3,如果未发现合适的观测点,则该数据运行流程退出

3.4 ASSERT检测机制
KCSAN提供有一种断言检测机制,检查在数据竞争模型以外的情况下提供竞争检测;


3.4.1 ASSERT集合

3.5 KCSAN特点

四、测试套件
4.1 KUNIT测试模型
KCSAN提供KUNIT的支持
创建多个access_thread线程用于测试用例函数的调用接口;
挂接console跟踪点,该跟踪点监控串口输出数据;如果有数据竞争报错,可以捕获并判断;
启动测试用例接口函数,实现测试函数的挂接并提供超时判定(缺省执行500毫秒);
在执行超时以后,判断输出是否与预想一致;并给出判断结果。

4.2 测试条件
1. 配置CONFIG_KCSAN_KUNIT_TEST=y使能KUNIT
2. KCSAN功能正常开启
4.3 测试环境
QEMU Linux 6.11 core 4 GCC11
测试覆盖:
1. 不同条件下的数据竞争data_race

2.断言函数数据竞争assert_exclusive_x

3. barrier/lock判定

五、过程与案例分析
5.1 KCSAN启动过程
1. 在完成KCSAN配置后,系统启动时有“kcsan:enable early”打印:

2.后台会实时进行观测点的监控与比对,如果比中会有”BUG:KCSAN”控制台打印来描述数据竞争的信息;这些信息包括调用函数、数据竞争地址、CPU号、进程号等;可在不同的测试场景进行压力测试;

3.在运行过程中,查看“KCSAN kernel debug”节点查看当前的状态,这些状态信息包括观测点、数据竞争、ASSERT报错等一系列信息;

5.2 案例一
描述:IGMP协议timer超时与事件函数在读写mr_ifc_count变量的数据竞争
net: igmp: fix data-race in igmp_ifc_timer_expire()

解决办法:
1. igmp_ifc_event/ igmp_ifc_timer_expire函数在读写mr_ifc_count变量存在数据竞争,需要使用LLKM 访问保护;
2. 修改调用mr_ifc_count点,使用READ_ONCE/WRITE_ONCE保证编译器的一致性;
3. mr_ifc_count和in_dev->mr_ifc_count值不等时启动重传机制;

5.3 案例二
描述:在taskstats_exit()中分配和测试任务统计时,会有一个竞争在读写sig->stats
When assiging and testing taskstats in taskstats_exit() there's a race when writing and reading sig->stats

解决办法:
1. 结构体成员sig->stats存在数据竞争,需要使用LLKM访问保护;
2. smp_load_acquire/smp_store_release函数解决CPU数据同步和编译器同步问题,适用于同一个函数内部的数据竞争;

六、总结
本文从工作原理、运行流程、测试方式等多个方面介绍了KCSAN,旨在让读者能够对KCSAN运行有一个直观的认识,利用KCSAN在产品中解决一些数据竞争问题;数据竞争是一个复杂问题,用KCSAN能帮助大家快速找到数据竞争问题,进而寻找方法解决或规避,本文更多传递是一种发现和解决此类问题的思路。
消杀器技术在不断地迭代和更新,也让大家多一份探寻世界、改变世界的机会;借此机会,站在巨人的肩膀上,让大家看得更远、走得更远,愿大家都有一个美好的明天。
七、参考文档
更多案例分享:
https://github.com/google/kernel-sanitizers/blob/master/kcsan/FOUND_BUGS.md
LKMM:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0124r2.html
KCSAN ASSERT:
https://www.kernel.org/doc/html/next/dev-tools/kcsan.html#c.ASSERT_EXCLUSIVE_ACCESS
KUNIT测试框架
https://kunit.dev/third_party/kernel/docs/api/test.html?highlight=kunit_expect_false
测试使用内核源码地址
https://kernel.source.codeaurora.cn/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.1.1&id=ebdb69c5b054f115ef5ff72f0bb2aaa1718904e6

长按关注内核工匠微信
Linux内核黑科技| 技术文章 | 精选教程
相关文章:
内核并发消杀器(KCSAN)技术分析
一、KCSAN介绍KCSAN(Kernel Concurrency Sanitizer)是一种动态竞态检测器,它依赖于编译时插装,并使用基于观察点的采样方法来检测竞态,其主要目的是检测数据竞争。KCSAN是一种检测LKMM(Linux内核内存一致性模型)定义的数据竞争(data race)的工…...
蓄水池抽样算法
蓄水池抽样,也称水塘抽样,是随机抽样算法的一种。基本抽样问题有一批数据(假设为一个数组,可以逐个读取),要从中随机抽取一个数字,求抽得的数字下标。常规的抽样方法是,先读取所有的…...
数据结构预算法之买股票最好时机动态规划(可买卖多次)
一.题目二.思路在动规五部曲中,这个区别主要是体现在递推公式上,其他都和上一篇文章思路是一样的。所以我们重点讲一讲递推公式。这里重申一下dp数组的含义:dp[i][0] 表示第i天持有股票所得现金。dp[i][1] 表示第i天不持有股票所得最多现金如…...
华为OD机试真题Java实现【蛇形矩阵】真题+解题思路+代码(20222023)
蛇形矩阵 蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。 例如,当输入5时,应该输出的三角形为: 1 3 6 10 15 2 5 9 14 4 8 13 7 12 11请注意本题含有多组样例输入。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Java)真题目录汇总 输入描述:…...
spring Bean的生命周期 IOC
文章目录 1. 基础知识1.1 什么是 IoC ?2. 扩展方法3. 源码入口1. 基础知识 1.1 什么是 IoC ? IoC,控制反转,想必大家都知道,所谓的控制反转,就是把 new 对象的权利交给容器,所有的对象都被容器控制,这就叫所谓的控制反转。 IoC 很好地体现了面向对象设计法则之一 —…...
详解cors跨域
文章目录同源策略cors基本概念cors跨域方式简单请求 simple request非简单请求- 预检请求CORS兼容情况CORS总结同源策略 在以前的一篇博客中有介绍,同源策略是一种安全机制,为了预防某些恶意的行为,限制浏览器从不同源文档和脚本进行交互的行…...
ARM uboot 源码分析7 - uboot的命令体系
一、uboot 命令体系基础 1、使用 uboot 命令 (1) uboot 启动后进入命令行环境下,在此输入命令按回车结束,uboot 会收取这个命令然后解析,然后执行。 2、uboot 命令体系实现代码在哪里 (1) uboot 命令体系的实现代码在 uboot/common/cmd_xx…...
物理服务器与云服务器备份相同吗?
自从云计算兴起以来,服务器备份已经从两阶段的模拟操作演变为由云服务器备份软件执行的复杂的多个过程。但是支持物理服务器和虚拟服务器之间的备份相同吗?主要区别是什么?我们接下来将详细讨论这个问题。 物理服务器与云服务器备份的区别 如果您不熟悉虚拟服务器…...
【Linux】system V共享内存 | 消息队列 | 信号量
🌠 作者:阿亮joy. 🎆专栏:《学会Linux》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉system V共…...
FSC的宣传许可 答疑
【FSC的宣传许可 答疑】问:已经采购了认证产品但没有贴FSC标签,是否可以申请宣传许可?答:不可以。要宣传您采用了FSC认证产品的前提条件之一是产品必须是认证且贴有标签的。如果产品没有贴标,则不可申请宣传许可。您的…...
Leetcode力扣秋招刷题路-0100
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 100. 相同的树 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是…...
协作对象死锁及其解决方案
协作对象死锁及其解决方案 1.前言 在遇到转账等的需要保证线程安全的情况时,我们通常会使用加锁的方式来保证线程安全,但如果无法合理的使用锁,很可能导致死锁。或者有时我们使用线程池来进行资源的使用,如调用数据库࿰…...
良许也成为砖家啦~
大家好,我是良许。 没错,良许成为砖家啦,绝不是口嗨,有图有真相! 有人会说,咦,这明明是严宇啊,跟你良许有啥关系? 额。。老读者应该知道良许的来历—— 鄙人真名严宇&a…...
Java中的编程细节
前言: 学习过程中有不少时候遇到一些看似简单,做起来事倍功半的问题。我也想自己是个聪明人,学东西一听就懂,一学就会,马上就能灵活应用。但这种事不能强求,要么自己要看个十遍二十遍最后理清逻辑…...
Yolov8从pytorch到caffe (一) 环境搭建
Yolov8从pytorch到caffe (一) 环境搭建 1. 创建虚拟环境2. 安装pytorch与v8相关库3. 测试安装是否成功4. 测试推理图像在windows上配置YOLOv8的环境,训练自己的数据集并转换到caffemodel1. 创建虚拟环境 利用conda创建虚拟环境 conda create -n yolo python=3.8 -y 并进入ac…...
2023年CDGA考试-第16章-数据管理组织与角色期望(含答案)
2023年CDGA考试-第16章-数据管理组织与角色期望(含答案) 单选题 1.在定义任何新组织或尝试改进现有组织之前了解当前组织的哪些方面非常重要? A.企业文化、运营模式和人员 B.业务战略、技术战略、数据战略 C.工具、方法和流程 D.事业环境因素、组织过程资产,行动路线图 …...
Stream——集合数据按照某一字段排序
文章目录前言假设业务场景排序前的准备正序排序1、数据集合的判空 Optional.isPresent()2、使用sort排序3、将排序后的数据流转换为list你以为这样就完了?倒序排序前言 之前,针对Stream链式编程中的几个方法做了大致的说明。详情可以参考: J…...
ubuntu:20.04编译arrow
1)拉取代码 git clone https://github.com/apache/arrow.git 2)切换分支 git checkout apache-arrow-11.0.0 3)拉入测试数据并设置环境变量 pushd arrow git submodule update --init export PARQUET_TEST_DATA"${PWD}/cpp/submodules/parquet-testing/da…...
2023如果纯做业务测试的话,在测试行业有出路吗?
直接抛出我的结论:手工做业务类测试,没有前途。 个人建议赶紧从业务测试跳出来,立即学习代码,走自动化测试方向。目前趋势,业务测试需要用自动化做。 为了让大家能够信服我的观点,本文将从以下方面进行阐…...
golang grpc ssl
无CA场景 在不考虑CA的场景下呢,client有client.key和client.crt,server有server.key和server.crt,生成方式可以如下: $ openssl genrsa -out server.key 2048 $ openssl req -new -x509 -days 3650 \-subj "/CGB/LChina/Og…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
