Linux 的清 CPU cache 的函数是哪个? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
amiwrong123
V2EX    程序员

Linux 的清 CPU cache 的函数是哪个?

  amiwrong123 2023-09-05 22:11:43 +08:00 2829 次点击
这是一个创建于 769 天前的主题,其中的信息可能已经有所发展或是发生改变。

目前我正在 linux 上,写一个用户态的一个 c 程序。里面有一个逻辑是,去写了一段 RAM ,但写的动作实际上只发生在了 x86 CPU 的 cache 里面,还没有真正写到 RAM 里,然后这导致了错误发生(可以认为我需要结合 DMA 做一些操作,但 DMA 需要读到的东西还在 CPU 的 cache 里面呢)。

所以我想知道,linux 里有提供这种函数吗?(类似 arm ,都会提供这种函数的)

另外,我在网上搜,搜到的 全是 shell 里执行的命令:sync; echo 1 > /proc/sys/vm/drop_caches。这个关键词到底该怎么搜索。

33 条回复    2023-09-07 19:05:37 +08:00
Yourshell
    1
Yourshell  
   2023-09-05 22:15:53 +08:00
你用 C 也可以写/proc/sys/vm/drop_caches 啊
Yourshell
    2
Yourshell  
   2023-09-05 22:16:43 +08:00
Linux 文件就是接口
geelaw
    3
geelaw  
   2023-09-05 22:17:24 +08:00 via iPhone
关键词是 linux flush cpu cache
Yourshell
    4
Yourshell  
   2023-09-05 22:17:53 +08:00
codehz
    5
codehz  
   2023-09-05 22:21:58 +08:00
我觉得这里有很多概念上的问题啊。。。
/proc/sys/vm/drop_caches 这个显然和 cpu cache 没有关系
你要 bypass cpu cache 的话,直接 volatile 不就好了
amiwrong123
    6
amiwrong123  
OP
   2023-09-05 22:26:13 +08:00
@codehz
指针加 volatile 应该也可以 达到我的目的,但可能效率会变低。

所以还是想用 清 cache 的函数。
leonshaw
    7
leonshaw  
   2023-09-05 22:28:36 +08:00 via Android
XY 问题
ljn917
    8
ljn917  
   2023-09-05 22:31:34 +08:00 via Android
感觉 memory order/fence 可以,但是需要 C11

https://en.cppreference.com/w/c/atomic/memory_order
codehz
    9
codehz  
   2023-09-05 22:31:51 +08:00
@amiwrong123 (小寄巧:用 *(volatile int __attribute__((force)) *)&x = 1 写入
内核也在用,不过把 __attribute__((force)) 加了个宏__force 简化)
geelaw
    10
geelaw  
   2023-09-05 22:32:44 +08:00 via iPhone
读了一下文档,看起来 drop_caches 只能清除文件系统里没有写过的缓存,sync 的作用是刷新所有文件,此外楼主的命令的影响范围是整个系统,而不是自己的进程,这样做几乎永远是错误的。

@codehz #5 可能楼主需要写很多内容后一起刷新?
codehz
    11
codehz  
   2023-09-05 22:34:26 +08:00
不过 linux 用内核用是有正当理由的,你这是 x86 带有硬件 dma 或者别的硬件内存映射技术一类的吗,那样用户态也访问不到吧
codehz
    12
codehz  
   2023-09-05 22:35:54 +08:00
@geelaw 我感觉根本不是一个目的啊,drop_caches drop 的是 page cache 这些,和 cpu 缓存一点关系都没,下文提及的也看出不太像是访问文件的问题)
amiwrong123
    13
amiwrong123  
OP
   2023-09-05 22:37:51 +08:00
@codehz
是的,用到了硬件的 DMA 。
用户态是可以访问的呀,只要最终映射出一个虚拟地址出来给 CPU 用就好了。我的程序逻辑很简单,以 RAM 作为交互,简单来说,CPU 先往 RAM (也就是内存条)里写,然后 DMA 从 RAM 里读。
sujin190
    14
sujin190  
   2023-09-05 22:40:07 +08:00 via Android
没听说过还有手动清 cpu cache line 的,并发不一致也仅限于多核并发写,cpu 都自己管理好了和内存一致,时钟周期级别的一致,否则那么多程序都只是 lock 一下就能从内存读到正确值岂不是都要挂了,如果你硬要说有那应该就是 lock 之类的操作触发总线同步来标记 cache line 无效就是了吧
shimanooo
    15
shimanooo  
   2023-09-05 22:43:00 +08:00
volatile?
polaa
    16
polaa  
   2023-09-05 22:43:32 +08:00
缓存一致性问题 关键词 Cache coherence

函数 : __clear_cache

指令 clflash wbinvd
codehz
    17
codehz  
   2023-09-05 22:45:46 +08:00
@amiwrong123 参考这个 https://github.com/ikwzm/udmabuf mmap 的时候加一个 O_SYNC
codehz
    18
codehz  
   2023-09-05 22:52:59 +08:00
虽然理论上这种情况还有编译器优化的问题,也就是如果 a b a 这样写,可能会跳过中间的 b
再用前面说的 volatile 转换方式也不迟(
codehz
    19
codehz  
   2023-09-05 22:56:13 +08:00
哦,不对,编译器优化用 asm volatile("" ::: "memory");隔开就够了,O_SYNC 配合合适的用户态 dma 映射实现,应该就足够了
(不过用户态 dma 你还是得考虑调度的问题,没准你循环写入的时候进程被调度走了呢)
polaa
    20
polaa  
   2023-09-05 22:57:09 +08:00
然后你的这种做法的关键词是 self-modifying code ,但是我只接触过 arm 架构的 x86 架构不熟悉

可以参考一下 intel 的 Intel 64 and IA-32 Architectures Optimization Reference Manual
@polaa
codehz
    21
codehz  
   2023-09-05 23:05:50 +08:00
udmabuf 能 O_SYNC 的原因是加了这个参数后,就会在内核里用 dma_sync_single_for_cpu 来同步 cpu 缓存(
其他普通的实现可不一定有这个)
amiwrong123
    22
amiwrong123  
OP
   2023-09-05 23:13:13 +08:00
@codehz #19
理解你说的意思,就是说,如果一个进程 malloc 了一片空间,这片空间只是属于这个进程的,但可能进程调度,把 RAM 的东西从内存条上调度走了。
不过我这个应该没有这个担心,因为不是用户态 malloc 的空间,是直接 搞了一块 连续的物理地址出来,再映射到虚拟地址。
amiwrong123
    23
amiwrong123  
OP
   2023-09-05 23:14:38 +08:00
@codehz #21
代码是这样的,是用 devmem 获得的 fd ,获得时是使用了 O_SYNC 的(不知道为啥,还是没起作用)。然后用这个 fd 进行 mmap ,获得了一个虚拟地址。
nuk
    24
nuk  
   2023-09-05 23:20:24 +08:00
Memory barrier 吧,硬件不同实现不同
codehz
    25
codehz  
   2023-09-05 23:21:23 +08:00
@amiwrong123 前面说的被调度走指的不是说内存映射也炸了
而是说 dma 硬件处理上可能会有不低概率观察到只进行到一半的修改(
后面补充的 o sync 就是为了应对你说的这个的 dev mem 的问题,正经解决方法就是用 udmabuf 那个模块去映射,效率也高一点
nuk
    26
nuk  
   2023-09-05 23:52:18 +08:00
原来是 DMA ?如果直接 mmap /dev/mem 的话,DMA 的内存区域本身就是 uncache 的,如果 dynamic DMA ,那不能直接用户态 mmap 创建 dma 内存,需要内核模块先分配 dma 内存。
liuminghao233
    27
liuminghao233  
   2023-09-06 00:07:48 +08:00 via iPhone
内存屏障做的是 cache 可见性同步,不能保证刷入 ram
你需要 CLFLUSH ,可以把 l1 l2 l3 的 cache 都刷掉
用 _mm_clflush 应该就可以
ryd994
    28
ryd994  
   2023-09-06 00:31:47 +08:00 via Android
memory barrier 只是避免编译器优化,缓存一致性仍然由 CPU 自己维护,也就无法解决 dma 的问题。
dma 是设备修改内存,CPU 无法维护缓存一致性
volatile 就是最简单的办法。

正规做法是
dma_map_single(), dma_sync_single_for_device(), dma_unmap_single(), dma_sync_single_for_cpu()
这几个 API 。合理使用的话,它们会处理 dma 一致性问题
ryd994
    29
ryd994  
   2023-09-06 00:34:24 +08:00 via Android
顺带一提,我用的关键字是
dma sync cpu cache

你不应该搜 Linux cache 。因为,cache 有很多种。CPU cache 也是 cache ,Page cache 也是 cache 。一般用户是不可能需要清 CPU cache 的,只有写驱动的人才需要。所以直接搜 cache ,大部分内容都是 Page cache
feather12315
    30
feather12315  
   2023-09-06 00:55:32 +08:00 via Android
__builtin___clear_cache

@polaa #20 这个 func
jimages
    31
jimages  
   2023-09-06 01:05:05 +08:00
WBINVD 指令,不过这个执行只能在特权模式下执行,你需要看一下操作系统有没有提供这个指令的函数,比如 windows 好像提供了 https://learn.microsoft.com/en-us/cpp/intrinsics/wbinvd?view=msvc-170
linux 不太清楚
jimages
    32
jimages  
   2023-09-06 01:08:46 +08:00
这个 repo 写了一个 linux 扩展,你也许可以使用 https://github.com/batmac/wbinvd/blob/master/wbinvd.c
codehz
    33
codehz  
   2023-09-07 19:05:37 +08:00
@ryd994 udmabuf 是在 O_SYNC 的时候做了 dma_sync_single_for_cpu 的,所以直接 mmap 也可以了
关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3882 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 26ms UTC 10:19 PVG 18:19 LAX 03:19 JFK 06:19
Do have faith in what you're doing.
ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86