为什么将函数参数标记为易失性
我目前正在阅读 PostgreSql 代码。以下是缓冲区管理器的摘录:
static void WaitIO(volatile BufferDesc *buf);
static bool StartBufferIO(volatile BufferDesc *buf, bool forInput);
static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty,
我知道 volatile 关键字通常用于设备驱动程序和嵌入式系统中。有关键字的解释。
当在类型定义中使用关键字 volatile 时,它向编译器指示应如何处理变量。主要是告诉编译器,由于程序或当前执行行外部的操作,变量的值可能随时发生变化。 (来源)
那么为什么某些函数参数被声明为易失性的呢?我不希望 DMA 改变指针位置。那么这里会发生什么呢?
I am currently reading the PostgreSql code. Here is an excerpt from the buffer manager:
static void WaitIO(volatile BufferDesc *buf);
static bool StartBufferIO(volatile BufferDesc *buf, bool forInput);
static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty,
I know the volatile keyword is usually used for device drivers and in embedded systems. There is an explanation of the keyword.
When the keyword volatile is used in the type definition it is giving an indication to the compiler on how it should handle the variable. Primarily it is telling the compiler that the value of the variable may change at any time as a result of actions external to the program or current line of execution.
(Source)
So why are certain function arguments declared as volatile? I don't expect that DMA changes the pointer location. So what happens here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
volatile BufferDesc *buf
表示 buf指向的数据是易失性的,而不是buf
包含的指针是不稳定的。 (这将是 BufferDesc * 易失性 buf 。)来自 您链接到的页面:
重新回答您问题的这一部分:
大概是因为它指向的数据可能会以编译器不一定知道的方式发生变化。
volatile
关键字的作用是防止编译器应用假设数据不会以它不知道的方式更改的优化。volatile BufferDesc *buf
means that the data thatbuf
points to is volatile, not that the pointer contained bybuf
is volatile. (That would beBufferDesc * volatile buf
.)From the page you linked to:
Re this part of your question:
Presumably because the data it points to can change in a way that the compiler wouldn't necessarily know about. The
volatile
keyword is there to prevent the compiler applying optimizations that assume the data doesn't change in ways it doesn't know about.不是地点,而是内容。这正是它的目的......
Not the location, but maybe the content. And that's exactly what it is about...
访问文件时,数据库实现不依赖操作系统缓冲区和缓存。他们更喜欢实现自己的缓存系统并直接访问物理磁盘上的文件,以解决可靠性问题:数据必须刷新到物理磁盘。 (它们使用 O_DIRECT 选项来执行对物理磁盘的直接访问。)
您向我们展示的 3 个函数让我想到了来自磁盘的数据的异步处理。 (StartBufferIO()、TerminationBufferIO() 等)。老实说,我不确定它们的目的是什么,但是根据我对数据库实现和这些函数名称的了解,我想说缓冲区内容可能会被“磁盘”本身使用磁盘上文件中的数据进行修改(或任何设备),因此需要标记为易失性。
这个假设与您对易失性关键字通常用于什么的通常解释相结合:设备驱动程序。
Databases implementation does not rely on the OS buffers&caches when accessing files. They prefer to implement they own cache system and get direct access to the file on the physical disk, for reliability issues: data MUST to be flushed to the physical disk. (They use the O_DIRECT option to perform direct access to physical disk.)
The 3 functions you are showing us make me think of asynchronous handling of data coming from the disk. (StartBufferIO(), TerminatedBufferIO() and so on). Honestly I am not sure of what is their purpose, but based on what I know about databases implementation, and those function names, I would say that the buffer content might be modified by the "disk" itself with data from the file on the disk (or whatever device), and therefore needs to be flaged as volatile.
This hypothesis joins your usual interpretation of what the volatile keyword is usually used for: device drivers.
DMA 并不是使用“易失性”的唯一原因。它对于多线程和共享内存应用程序也很有用,其中另一个线程可能会更改此代码引用的内存。我确信 PostgreSql 是多线程的,所以这可能是这里使用 volatile 的原因。
DMA isn't the only reason to use "volatile". It's also useful for multithreaded and shared memory applications, where another thread may change memory referenced by this code. I'm sure that PostgreSql is multi-threaded, so this is a likely reason why volatile is being used here.
编译器在优化时通常做的一件事是删除死代码,因此,如果您对一个从未读取过的变量执行一些操作,并且其结果无用,编译器可能只会删除它,以及删除影响它的其余操作。当您调试代码或执行某种基准测试时,这种行为可能会非常烦人。如果您将变量声明为易失性,您会警告编译器它可能会被外部库或程序使用,以及该关键字可能具有的其他含义。那么它就不应该将其视为死代码。
One thing a compiler usually does when optimising is removing dead code, so if you do some operations with a variable that its never read neither and its result is useless compiler will probably just remove it, as well as removing the rest of operations that affects it. That behaviour can be very annoying when your debug a code ore your are performing some kind of benchamrks. If you declare as volatile a variable you alert the compiler it could be used by external libraries or programs, among other implications the keyword may have. Then it should never treat it as dead code.