为什么POSIX mmap没有返回volatile*?

Jos*_*vin 10 c posix pointers mmap volatile

Mmap返回void*,但不是a volatile void*.如果我使用mmap来映射共享内存,那么另一个进程可能正在写入该内存,这意味着来自同一内存位置的两个后续读取可能会产生不同的值 - 这是指volatile的确切情况.那么为什么它不会返回一个易变的空隙*?

我最好的猜测是,如果你有一个专门写入共享内存段的进程,它不需要通过volatile指针查看共享内存,因为它总能正确理解存在的内容; 编译器为防止冗余读取所做的任何优化都无关紧要,因为没有其他任何内容可以写入并更改其下的值.还是有其他一些历史原因?我倾向于说返回volatile void*将是一个更安全的默认值,那些想要进行优化的人可以手动转换为void*.

POSIX mmap说明:http://opengroup.org/onlinepubs/007908775/xsh/mmap.html

caf*_*caf 7

实现共享内存只是其使用的一小部分mmap().事实上,最常见的用途是创建私有映射,包括匿名和文件支持.这意味着,即使我们接受了关于volatile为共享内存访问要求合格指针的争论,在一般情况下这样的限定符也是多余的.

请记住,您始终可以在不进行强制转换的情况下最终限定符添加到指针类型,但不能删除它们.因此,使用当前mmap()声明,您可以这样做:

volatile char *foo = mmap();  /* I need volatile */
Run Code Online (Sandbox Code Playgroud)

还有这个:

char *bar = mmap();  /* But _I_ do not */
Run Code Online (Sandbox Code Playgroud)

根据您的建议,普通案例中的用户必须抛弃挥发性物品.


Bor*_*lid 6

贯穿许多软件系统的深刻假设是大多数程序员都是顺序程序员.这最近才开始发生变化.

mmap有许多与共享内存无关的用途.如果程序员正在编写多线程程序,他们必须采取自己的步骤来确保安全.使用互斥锁保护每个变量不是默认值.同样地,mmap假设另一个线程将对同一共享内存段进行有争议的访问,或者甚至不会被另一个线程访问如此映射的段.

我也是不相信标记的回报mmap作为volatile将对此产生影响.程序员仍然必须确保访问映射区域的安全性,不是吗?


nos*_*nos 5

易失性只会覆盖一次读取(根据架构可能是 32 位或其他,因此非常有限。通常您需要写入超过 1 个机器字,并且无论如何您都必须引入一些某种锁定。

即使它是易失性的,您也可以轻松地让 2 个进程从同一内存读取不同的值,所需要的只是 3. 进程在从 1. 进程读取和从 2. 进程读取之间的纳秒内写入内存。 .process(除非你能保证两个进程在几乎完全相同的时钟周期内读取相同的内存。

因此 - mmap() 尝试处理这些事情是毫无用处的,最好留给程序员如何处理对内存的访问并在需要时将指针标记为易失性 - 如果内存是共享的 - 你需要让所有相关方进行合作,并了解如何更新彼此相关的内存 - 某些内容超出了 mmap 的范围,并且某些 volative 无法解决。

  • @Joseph Garvin,你是对的,它不会被缓存(尽管在多核 x86 机器上,它可以缓存在 l1/l2 缓存中,除非写入以 LOCK 操作码为前缀 - 添加 volatile 是行不通的),但没有任何停止当您读取该结构中的一个整数时,其他人会更改该结构中的一个字节 - 要点是,让 mmap 返回一个易失性指针几乎解决不了任何问题,因此程序员需要在需要时将该指针设置为易失性,并且由程序员来处理(更大的)锁定/协作访问问题。 (3认同)