首页 > 其他分享 >为什么不应该使用"volatile"类型的类 【ChatGPT】

为什么不应该使用"volatile"类型的类 【ChatGPT】

时间:2023-12-08 23:12:46浏览次数:28  
标签:访问 volatile 内核 类型 shared ChatGPT data 内存

为什么不应该使用"volatile"类型的类

C程序员通常认为volatile意味着变量可以在当前执行线程之外被改变;因此,当使用共享数据结构时,他们有时会倾向于在内核代码中使用它。换句话说,他们已经将volatile类型视为一种简单的原子变量,但实际上并非如此。在内核代码中几乎从不正确地使用volatile;本文描述了其中的原因。

理解volatile的关键点是,它的目的是抑制优化,而这几乎从不是我们真正想要做的。在内核中,我们必须保护共享数据结构免受不希望的并发访问,这是完全不同的任务。保护不希望的并发性的过程也会以更高效的方式避免几乎所有与优化相关的问题。

与volatile类似,使并发访问数据安全的内核原语(自旋锁、互斥锁、内存屏障等)旨在防止不希望的优化。如果它们被正确使用,就不需要再使用volatile。如果仍然需要volatile,那么代码中几乎肯定存在bug。在编写正确的内核代码中,volatile只会减慢速度。

考虑一个典型的内核代码块:

spin_lock(&the_lock);
do_something_on(&shared_data);
do_something_else_with(&shared_data);
spin_unlock(&the_lock);

如果所有的代码都遵循锁定规则,那么在持有the_lock时,shared_data的值不会意外改变。任何想要操作该数据的其他代码都将在锁上等待。自旋锁原语充当内存屏障 - 它们明确地被编写为如此 - 这意味着数据访问不会在它们之间进行优化。因此,编译器可能认为它知道shared_data中的内容,但是spin_lock()调用,由于它充当内存屏障,将迫使它忘记它所知道的任何内容。对该数据的访问不会出现优化问题。

如果shared_data被声明为volatile,那么锁定仍然是必要的。但是编译器也将阻止在临界区内对shared_data的访问进行优化,因为我们知道没有其他人会与之一起工作。在持有锁时,shared_data不是volatile的。在处理共享数据时,适当的锁定使volatile变得不必要,甚至可能有害。

volatile存储类最初是为了内存映射的I/O寄存器而设计的。在内核中,寄存器访问也应该受到锁的保护,但是我们也不希望编译器在临界区内对寄存器访问进行"优化"。但是,在内核中,I/O内存访问总是通过访问器函数进行的;直接通过指针访问I/O内存是不被赞同的,并且在所有体系结构上都不起作用。这些访问器被编写为防止不希望的优化,因此,再次强调,volatile是不必要的。

还有一种情况可能会诱使人们使用volatile,那就是处理器正在忙等待变量的值。执行忙等待的正确方法是:

while (my_variable != what_i_want)
    cpu_relax();

cpu_relax()调用可以降低CPU功耗或让出给超线程的双处理器;它也恰好作为编译器屏障,因此再次强调,volatile是不必要的。当然,忙等待通常是一种不友好的行为。

在内核中,仍然有一些罕见的情况下,volatile是有意义的:

  • 上述的访问器函数在直接I/O内存访问有效的体系结构上可能使用volatile。实质上,每个访问器调用本身就成为一个小的临界区,并确保访问按照程序员的预期进行。

  • 内联汇编代码会更改内存,但没有其他可见的副作用,这可能会被GCC删除。在asm语句中添加volatile关键字将防止此删除。

  • jiffies变量是特殊的,因为每次引用它时它的值可能不同,但可以在没有特殊锁定的情况下读取。因此,jiffies可以是volatile的,但强烈不建议添加其他此类变量。在这方面,jiffies被认为是一个"愚蠢的遗留问题"(Linus的话);修复它将比它值得的麻烦多。

  • 可能会被I/O设备修改的一致内存中的数据结构指针有时可能是volatile的。网络适配器使用的环形缓冲区,其中适配器更改指示已处理哪些描述符的指针,就是这种情况的一个例子。

对于大多数代码,上述关于volatile的理由都不适用。因此,使用volatile很可能被视为一个bug,并将对代码带来额外的审查。被诱惑使用volatile的开发人员应该退一步,思考他们真正想要实现什么。

通常欢迎删除volatile变量的补丁 - 只要它们附带了合理的理由,表明并发问题已经经过适当的思考。

标签:访问,volatile,内核,类型,shared,ChatGPT,data,内存
From: https://www.cnblogs.com/pengdonglin137/p/17889246.html

相关文章

  • 关于Linux稳定版本的一切你想知道的内容 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/process/stable-kernel-rules.html#关于Linux稳定版本的一切你想知道的内容关于哪些补丁被接受,哪些不被接受进入“-stable”树的规则:它或等效的修复必须已经存在于Linus的树(上游)中。它必须明显正确且经过测试。它的大小不能超......
  • Linux 内核补丁提交的清单 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/process/submit-checklist.html这是一个关于Linux内核补丁提交的清单,开发者如果想要更快地看到他们的内核补丁被接受,应该做一些基本的事情。这些事情都超出了《Documentation/process/submitting-patches.rst》和其他关于提交Linux......
  • 进一步内核文档索引【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/process/kernel-docs.html进一步内核文档索引像这样的文档的需求在linux-kernel邮件列表中变得明显,因为相同的问题一次又一次地出现,要求指向信息。幸运的是,随着越来越多的人开始使用GNU/Linux,越来越多的人对内核感兴趣。但是仅仅阅......
  • Linux内核驱动程序接口 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/process/stable-api-nonsense.html#binary-kernel-interfaceLinux内核驱动程序接口(回答你的所有问题以及更多)[email protected]这篇文章旨在解释为什么Linux没有二进制内核接口,也没有稳定的内核接口。注意请注意......
  • 处理回归 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/process/handling-regressions.html#处理回归我们不会引起回归-本文描述了对开发人员来说,“Linux内核开发的第一法则”在实践中意味着什么。它是对报告回归的补充,该报告从用户的角度涵盖了这个主题;如果你从未阅读过那篇文章,至少在继续......
  • Linux内核许可规则 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/process/license-rules.htmlLinux内核许可规则Linux内核仅在GNU通用公共许可证第2版(GPL-2.0)的条款下提供,如LICENSES/preferred/GPL-2.0中所述,并在LICENSES/exceptions/Linux-syscall-note中描述了明确的系统调用例外情况,如COPYING文件中......
  • 内核维护者手册 - 维护者入口配置文件【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/maintainer/maintainer-entry-profile.html维护者入口配置文件维护者入口配置文件是对顶层流程文档(提交补丁、提交驱动程序等)的补充,其中包括子系统/设备驱动程序本地习俗以及有关补丁提交生命周期的详细信息。贡献者使用此文档来调整他......
  • 内核维护者手册 - 修改补丁【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/maintainer/modifying-patches.html修改补丁如果你是一个子系统或分支的维护者,有时你需要稍微修改你收到的补丁才能合并它们,因为你的代码与提交者的代码并不完全相同。如果你严格遵守开发者证书的规则(c),你应该要求提交者重新生成补丁,但......
  • 内核维护者手册 - 变基和合并【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/maintainer/rebasing-and-merging.html重基和合并一般来说,维护一个子系统需要熟悉Git源代码管理系统。Git是一个功能强大的工具,具有许多特性;通常情况下,对于这类工具来说,使用这些特性有正确和错误的方式。本文特别关注重基和合并的使......
  • 内核维护者手册 - 创建拉取请求【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/maintainer/pull-requests.html创建拉取请求本章描述了维护者如何创建并提交拉取请求给其他维护者。这对于将一个维护者的更改传输到另一个维护者的树中非常有用。这份文档是由TobinC.Harding(当时并不是一位经验丰富的维护者)根据Greg......