什么时候实际的write()发生在C?

时间:2012-10-24 11:51:21

标签: c unix

执行write()系统调用时会发生什么?

假设我有一个程序使用write()函数调用将某些数据写入文件。现在C库有自己的内部缓冲区,OS也有自己的缓冲区。

这些缓冲区之间发生了什么交互?

当C库缓冲区被完全填满时,它是否写入OS缓冲区并且当OS缓冲区完全填满时,是否对文件进行了实际写入?

我正在寻找一些详细的答案,有用的链接也会有所帮助。请考虑UNIX系统的这个问题。

6 个答案:

答案 0 :(得分:3)

据我所知......

write()函数是一个较低级别的东西,其中库不缓冲数据(与库{/ 1}}不同,其中库可以/可以缓冲数据。)

尽管如此,唯一的保证是操作系统会在下一个fwrite()完成之前将数据传输到磁盘驱动器。但是,硬盘驱动器通常有自己的内部缓冲区(有时)超出操作系统的控制范围,因此即使后续的fsync()已完成,也可能发生电源故障或在实际写入数据之前发生的事情。磁盘驱动器的内部缓冲区到磁盘的物理介质。

基本上,如果你真的必须确保你的数据实际写入磁盘的物理媒体;那么你需要重新设计你的代码以避免这个要求,或接受(小)失败的风险,或确保硬件能够(例如获得UPS)。

答案 1 :(得分:3)

write()系统调用(实际上是所有系统调用)只不过是应用程序和操作系统之间的契约。

  • 对于“普通”文件,write()只将数据放在缓冲区上,并将缓冲区标记为“脏”
  • 在将来的某个时间,这些脏缓冲区将被收集并实际写入磁盘。这可以通过fsync()
  • 强制执行
  • 这是由mounted-filesystem-table
  • 中的.write()“method”完成的
  • 这将调用硬件的.write()方法。 (可能涉及另一级缓冲,如DMA)
  • 现代硬盘有自己的缓冲区,即使操作系统>控制器告诉他们,可能已经或可能没有实际写入物理磁盘。

现在,一些(异常)文件没有一个write()方法来支持它们。想象一下open()ing“/ dev / null”,并写一个缓冲区给它。系统可以选择不缓冲它,因为它永远不会被写入。

另请注意,write()的行为取决于文件的性质;对于网络套接字,write(fd,buff,size)可以在发送大小字节之前返回(write将返回发送的字符数)。但是,一旦他们被发送,就无法找到它们的位置。它们仍然可以在网络缓冲区中(例如,等待Nagle ......),或网络接口内的缓冲区,或者线路上某处的路由器或交换机中的缓冲区。

答案 2 :(得分:2)

write()将数据写入操作系统,使其对所有进程可见(如果它可以被其他进程读取)。操作系统如何缓冲它,或者何时将其永久写入磁盘,即库,操作系统,系统配置和特定于文件系统。但是,sync()可用于强制刷新缓冲区。

保证的是,POSIX要求在符合POSIX的文件系统上,read()可以证明在write()返回后发生的{{1}}必须返回写入的数据。

答案 3 :(得分:0)

由于您要求使用UNIX,因此必须记住,文件实际上可能位于已安装的FTP服务器上,例如。例如,文件/dev/proc也不是HDD上的文件。

此外,在Linux上数据不是直接写入硬盘驱动器,而是有一个轮询过程,每隔一段时间刷新所有挂起的写入。

但同样,这些是实施细节,从您的计划的角度来看,这实际上不会影响任何事情。

答案 4 :(得分:0)

依赖于操作系统,请参阅man 2 sync和(在Linux上)man 8 sync中的讨论。

答案 5 :(得分:0)

多年前,操作系统应该实施“电梯算法”来安排写入磁盘。我们的想法是尽量减少磁盘写入磁头的移动,这样可以同时为访问磁盘的多个进程提供良好的吞吐量。