非阻塞在c / c ++中写入文件

时间:2010-12-13 22:45:08

标签: c++ c

我正在编写一个日志记录程序,我需要每秒读取一次串行,然后打印到日志文件。 问题是,有时候某些东西会阻碍我的循环并且数据会被备份。在对循环中的每个活动进行计时之后,我注意到将数据打印到日志文件的函数有时会花费太多时间。我正在研究非阻塞写入文件,并根据这篇文章:

File writing with overlapped IO vs file writing in a separate thread

默认情况下,“写入文件”不应该阻止我的程序。但它似乎是。

我正在使用MS visual studio EX,我正在编写一个consol c ++应用程序。有人可以告诉我默认情况下fprintf<<是否应该是非阻塞/异步的吗?如果没有,有没有办法让它们如此?

4 个答案:

答案 0 :(得分:9)

以下是Linux中的工作原理:

由于内核缓冲,不能阻止对常规文件的写入/读取。但是,当内核耗尽内存进行缓冲时,它们会阻塞。

来自 Linux编程接口:Linux和UNIX系统编程手册

  

非阻塞模式可以与设备(例如,终端和设备)一起使用   伪终端),管道,FIFO和插座。 (因为文件描述符   对于管道和套接字不是使用open()获得的,我们必须启用   这个标志使用了章节中描述的fcntl()F_SETFL操作   5.3。)

     

O_NONBLOCK通常会被常规文件忽略,因为内核缓冲区缓存可确保常规文件上的I / O不会阻塞,   如第13.1节所述。但是,O_NONBLOCK确实有效   对于使用强制文件锁定的常规文件(Section   55.4)。

从UNIX环境中的高级编程第二版

  

我们还说不考虑与磁盘I / O相关的系统调用   即使磁盘文件的读取或写入可以阻止,也会很慢   打电话暂时。

来自http://www.remlab.net/op/nonblock.shtml

  

常规文件始终可读,并且始终可写。   这在相关的POSIX规范中有明确说明。我不能   强调这一点。将常规文件放在非阻塞中   绝对没有改变文件标志中的一位以外的其他效果。

     

从常规文件中读取可能需要很长时间。例如,如果它位于繁忙的磁盘上,则I / O调度程序可能需要这么多   用户会注意到应用程序被冻结的时间。

     

然而,非阻塞模式不起作用。它根本行不通。检查文件的可读性或可写性总是成功的   立即。如果系统需要时间来执行I / O操作,那么   将把任务从读或写中置于不可中断的睡眠中   系统调用。

答案 1 :(得分:2)

IO流通常是缓冲的,并且每隔一段时间就会刷新这些缓冲区(到操作系统,然后到磁盘),但是你几乎无法控制何时以及以什么频率(严格来说你可以,但是你不想要......)当冲洗发生时,你会看到你的异常值。

“非阻塞”和“异步”不是我将用于标准流的单词。如果你想减少这些延迟,考虑内存映射文件写入 - boost有一个很好的便携包装器用于内存映射文件。

答案 2 :(得分:0)

fprintf和&lt;&lt;默认情况下不要使用重叠IO写入,我相信没有选项可以打开它。重叠的IO不可移植。必须使用带有初始化重叠结构的WriteFile作为最后一个参数。

答案 3 :(得分:0)

根据您的描述,看起来您写的数据太少太多次了。 如果IO活动很高,则可能导致缓冲文件I / O出现延迟。如前所述,您可以使用基于内存的文件或使用块写入。 我们的想法是通过一次性写入多次写入来减少写入次数,因此不要写入500个字节的10次写入,而是每次写入5k。 在大多数操作系统中,典型的页面大小(和写入大小)大约为4k(不确定窗口)。 因此,尝试一些开源软件包或编写一个减少写入次数的包装器。