内存映射文件和指向易失对象的指针 [英] memory mapped files and pointers to volatile objects

查看:109
本文介绍了内存映射文件和指向易失对象的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对C和C ++中volatile语义的理解是,它将内存访问转换为文章.)

My understanding of the semantics of volatile in C and C++ is that it turns memory access into (observable) side effects. Whenever reading or writing to a memory mapped file (or shared memory) I would expect the the pointer to be volatile qualified, to indicate that this is in fact I/O. (John Regehr wrote a very good article on the semantics of volatile).

此外,我希望使用像memcpy()这样的功能来访问共享内存是不正确的,因为签名表明易失性限定已被丢弃,并且内存访问不会被视为I/O.

Furthermore, I would expect using functions like memcpy() to access shared memory to be incorrect, since the signature suggests the volatile qualification is cast away, and the memory access not be treated as I/O.

在我看来,这是支持std::copy()的一种论点,在该论点中,不会丢弃volatile限定符,并且将内存访问正确地视为I/O.

In my mind, this is an argument in favor of std::copy(), where the volatile qualifier won't be cast away, and memory accesses being correctly treated as I/O.

但是,我使用易失性对象的指针和std::copy()来访问内存映射文件的经验是,它的速度比仅使用memcpy()慢几个数量级.我很容易得出结论,也许clang和GCC在volatile的处理上过于保守.是这样吗?

However, my experience of using pointers to volatile objects and std::copy() to access memory mapped files is that it's orders of magnitude slower than just using memcpy(). I am tempted to conclude that perhaps clang and GCC are overly conservative in their treatment of volatile. Is that the case?

如果我想遵循标准的文字并将其恢复我所依赖的语义,那么关于volatile的共享内存有什么指导?

What guidance is there for accessing shared memory with regards to volatile, if I want to follow the letter of the standard and have it back the semantics I rely on?

标准 [intro.execution]§14的相关报价:

读取由易失性glvalue指定的对象,修改 对象,调用库I/O函数或调用 这些操作中的任何一个是否都是副作用,它们都是变化 在执行环境的状态.表达式的求值 (或子表达式)通常包括两种值计算 (包括为glvalue确定对象的身份 评估并获取先前分配给对象的值 prvalue评价)和引发副作用.当一个电话 库I/O函数返回或通过易失性glvalue进行访问 经过评估,即使有些副作用被认为是完全的, 调用(例如I/O本身)或隐式暗示的外部操作 易失性访问可能尚未完成.

Reading an object designated by a volatile glvalue, modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects. When a call to a library I/O function returns or an access through a volatile glvalue is evaluated the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile access may not have completed yet.

推荐答案

我对C和C ++中volatile语义的理解是,它将内存访问转换为I/O

My understanding of the semantics of volatile in C and C++ is that it turns memory access into I/O

不,它不会那样做. volatile所做的全部工作是从程序员与编译器进行通信,即可以通过其他方式"随时更改某个内存区域.

No it does not do that. All volatile does is to communicate from the programmer to the compiler that a certain memory area can be changed at any time, by "something else".

其他"可能是很多不同的东西.例子:

"Something else" might be a lot of different things. Examples:

  • 内存映射的硬件寄存器
  • 与ISR共享的变量
  • 从回调函数更新的变量
  • 与另一个线程或进程共享的变量
  • 通过DMA更新的内存区域

由于标准(5.1.2.3)保证对易失性对象的访问(读/写)可能不会被优化,因此volatile也可用于阻止某些编译器优化,这在硬件中最有用-相关编程.

Since the standard (5.1.2.3) guarantees that an access (read/write) to a volatile object may not get optimized away, volatile can also be used to block certain compiler optimizations, which is mostly useful in hardware-related programming.

每当读取或写入内存映射文件(或共享内存)时,我希望指针是易失性的

Whenever reading or writing to a memory mapped file (or shared memory) I would expect the the pointer to be volatile qualified

不一定,不是.数据的性质无关紧要,仅取决于数据的更新方式.

Not necessarily, no. The nature of the data doesn't matter, only how it is updated.

我希望使用memcpy()之类的函数访问共享内存是不正确的

I would expect using functions like memcpy() to access shared memory to be incorrect

总体而言,这取决于您对共享内存"的定义.这是您整个问题的一个问题,因为您一直在谈论共享内存",这不是一个正式的,定义明确的术语.与另一个ISR/线程/进程共享的内存?

Overall it depends on your definition of "shared memory". This is a problem with your whole question, because you keep talking about "shared memory" which is not a formal, well-defined term. Memory shared with another ISR/thread/process?

是的,与另一个ISR/线程/进程可能共享的内存必须声明为volatile,具体取决于编译器.但这仅是 ,因为volatile可以防止编译器做出错误的假设并优化代码以错误的方式访问此类共享"变量.在较旧的嵌入式系统编译器上,特别容易发生这种情况.在现代的托管系统编译器上,它不是必需的.

Yes, memory shared with another ISR/thread/process might have to be declared as volatile, depending on compiler. But this is only becaue volatile can prevent a compiler from making incorrect assumptions and optimize code accessing such "shared" variables the wrong way. Something which was especially prone to happen on older embedded systems compilers. It shouldn't be necessary on modern hosted system compilers.

volatile不会导致内存屏障行为.它不会(强制)强制表达式以特定顺序执行.

volatile does not lead to memory barrier behavior. It does not (necessarily) force expressions to get executed in a certain order.

volatile当然不能保证任何形式的原子性.这就是将_Atomic类型限定符添加到C语言的原因.

volatile does certainly not guarantee any form of atomicity. This is why the _Atomic type qualifier was added to the C language.

所以回到复制问题-如果在几个ISR/线程/进程之间共享"了内存区域,那么volatile根本没有帮助.相反,您需要一些同步方式,例如互斥,信号量或关键部分.

So back to the copy issue - if the memory area is "shared" between several ISRs/threads/processes, then volatile won't help at all. Instead you need some means of synchronization, such as a mutex, semaphore or critical section.

在我看来,这是支持std :: copy()的一个论点,在该论点中,不会丢弃volatile限定符,并且将内存访问正确地视为I/O.

In my mind, this is an argument in favor of std::copy(), where the volatile qualifier won't be cast away, and memory accesses being correctly treated as I/O.

不,由于已经提到的原因,这是错误的.

No, this is just wrong, for the already mentioned reasons.

如果我想遵循标准的文字并让其返回我所依赖的语义,那么有什么指南可以访问有关volatile的共享内存?

What guidance is there for accessing shared memory with regards to volatile, if I want to follow the letter of the standard and have it back the semantics I rely on?

使用系统特定的API:通过互斥体/信号量/关键部分来保护内存访问.

Use system-specific API:s to protect the memory access, through mutex/semaphore/critical section.

这篇关于内存映射文件和指向易失对象的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆