为什么`aio_write`不允许并发缓冲区访问?

时间:2018-06-04 12:29:58

标签: c linux unix posix

Linux man-page for aio_write

  

在操作过程中,写出的缓冲区不得访问,否则可能会出现未定义的结果。

我强调“被访问”,严格解释不仅存储到缓冲区,还从缓冲区加载。

Mac OS X上的手册页

  

在请求排队之后但在请求完成之前,不允许修改异步I / O控制块结构或缓冲区内容。

这听起来更合理;缓冲区可以读取,但不能修改。但是,违规的后果仍然模糊不清。

考虑如何在操作系统中实现这一点,我不知道为什么读取访问会成为一个问题,并且我可以想象从并发写入的唯一问题是实际写入的数据可能是任意的将初始缓冲区内容和并发存储混合到缓冲区。

然而,未定义的行为开辟了许多可能性,并且考虑到这一点,我们可以获得访问时的SIGSEGV(底层页面被锁定以防止并发访问?),或者读取可能返回垃圾数据(文件系统在-place加密或压缩?),或文件可能留下永久不可读的块(块校验和,然后同时修改,然后写出?)。未定义的行为甚至不会排除崩溃存储设备固件或操作系统。

我的问题是,考虑到我们拥有的系统和硬件,实际上可以合理地发生什么?我认为这种语言有意模糊,不会限制未来的实施。

2 个答案:

答案 0 :(得分:1)

  

我的问题是,考虑到我们拥有的系统和硬件,实际上可以合理地发生什么?我认为这种语言有意模糊,不会限制未来的实施。

仔细查看API:

int aio_write(struct aiocb *aiocbp);

注意它没有指向const的指针?警告非常明确,一旦将aiocbp参数传递给aio_write(),数据就属于AIO代码,直到操作完成。您可以读取数据,但您可以合理地预期其状态是什么?根据API和规范,您无法预料到任何事情。即使观察到的行为也可能看起来完全随机。此外,出于性能(一致性)的原因,AIO可能会锁定该块的缓存行,而来自另一个核心的任何读取都可能会干扰整个系统的性能。

在没有锁定/解锁语义的情况下,无论何时将非const数据传递给另一个执行线程,您都无法合理地期望从该数据块中始终读取任何内容,直到您使用的任何API表示已完成任何操作你期望它的工作。无论他们的文档是否说明都是如此。

答案 1 :(得分:1)

Linux,BSD(MacOS是BSD风格),POSIX说不同的东西。

POSIX说:

  

用于更改进程内存空间的任何系统操作   异步I / O对于要更改的地址范围非常出色,   该行动的结果未定义。

Linux手册似乎更具限制性,有两种可能性:

  1. 这是解释的问题。作者可能会考虑写访问但只是写了访问
  2. 可能任何访问,因为实现可以自由使用任何可能禁止任何访问的机制(IO期间的严重锁定或保护)。
  3. BSD也说:

      

    如果请求成功入队,则为iocb-_aio_offset的值        可以在请求期间修改为上下文,因此该值不能为        在请求入队后引用

    因此明确禁止一些读取访问(对控制结构)。

    正如Martin在评论中所说:我不知道为什么有人想要在通知I / O完成之前访问structs / buffers / s 。但它的限制性太强了:好吧,对于写入访问来说很明显,但是可以想象(虽然不常见)你希望读取访问到缓冲区的场景IO(在显示帧缓冲内容时写入 - 或类似)。

    无论如何,如果你违反了限制,可能会发生任何不良事件,所以不要违反这些限制。