我正在编写一个日志记录程序,我需要每秒读取一次串行,然后打印到日志文件。 问题是,有时候某些东西会阻碍我的循环并且数据会被备份。在对循环中的每个活动进行计时之后,我注意到将数据打印到日志文件的函数有时会花费太多时间。我正在研究非阻塞写入文件,并根据这篇文章:
File writing with overlapped IO vs file writing in a separate thread
默认情况下,“写入文件”不应该阻止我的程序。但它似乎是。
我正在使用MS visual studio EX,我正在编写一个consol c ++应用程序。有人可以告诉我默认情况下fprintf
和<<
是否应该是非阻塞/异步的吗?如果没有,有没有办法让它们如此?
答案 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(不确定窗口)。 因此,尝试一些开源软件包或编写一个减少写入次数的包装器。