V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX  ›  程序员

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

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

    目前我正在 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   ·   实用小工具   ·   2529 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 16:02 · PVG 00:02 · LAX 08:02 · JFK 11:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.