如何检查是否有足够的空间在Windows中的c之前的WriteFile?

hPipe = CreateNamedPipe( lpszPipename, // pipe name PIPE_ACCESS_DUPLEX, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances 100, // output buffer size 100, // input buffer size 0, // client time-out NULL); // default security attribute DWORD totalBytesAvailable; PeekNamedPipe( hPipe , // __in HANDLE hNamedPipe, NULL, // __out_opt LPVOID lpBuffer, 0, // __in DWORD nBufferSize, NULL, // __out_opt LPDWORD lpBytesRead, &totalBytesAvailable, // __out_opt LPDWORD lpTotalBytesAvail, NULL // __out_opt LPDWORD lpBytesLeftThisMessage ); if(totalBytesAvailable allows) WriteFile( tmp_pipe, pBuffer, BufferLen, &dwWritten, NULL ); 

正如你所看到的我使用PeekNamedPipe来获得可用空间,但事实certificatetotalBytesAvailable始终为0 ,如何正确执行?

恕我直言,这种在做实际写入之前检查可用空间的方法是有缺陷的。

可能发生的情况是,当实际写入被执行时,其他一些并行运行的进程会填满可用磁盘空间的最后一位,从而导致WriteFile失败。

我只会依赖WriteFile返回的内容。

您无法以自己的方式确定可用空间。

虽然这个问题是关于管道的,但也有人可能会遇到它,寻找有关发现可用磁盘空间的一般信息,如果管道最终是一个文件,这可能仍然是有用的:

知识库文章“了解和使用GetDiskFreeSpace和GetDiskFreeSpaceEx”提供了有关用于确定可用磁盘空间的相关Win32 API的信息,或者直接访问以下API文档:

  • GetFreeDiskSpace
  • GetFreeDiskSpaceEx

在lpTotalBytesAvail参数中返回的值是可以从管道中读取而不是写入管道的字节数。 给你的信息来分配从管道读取数据的缓冲区。

写入管道或任何NT Krenel句柄时处理错误的正确方法是简单地执行对WriteFile()的调用并处理返回的任何错误。

检查然后写模式是无效的,并会产生的错误*永远不会发生在您的测试*有时在现场发生* …因此非常难以诊断和调试*最重要的是,这样的错误会惹恼您的用户。

原因在于目的地的状态可以在检查和实际写入之间改变。 这意味着调用WriteFile()的代码必须检查错误。 这意味着在调用WriteFile()之前检查一个前提条件是简单的额外代码,它不提供任何值。

这种模式不起作用的原因是Windows(以及所有其他操作系统 – 这不仅仅是一个Windows事物)不能把“check”和“write”当作原子操作,底层操作系统是完全异步的,通话之间可能会发生很多事情。

所以,如果你简单地调用WriteFile()并且做好错误处理,你的代码将会更简单更可靠。

-Foredecker

设置PIPE_NOWAIT而不是PIPE_WAIT。 然后,如果管道中没有足够的空间,则WriteFile将立即返回。
100对于I / O缓冲区大小似乎相当小! 你的管道是什么?

创建一个线程来处理写入管道,所以这不是一个作家挂起的问题,等待客户端清空管道?

关于检查的脆弱性然后写评论是正确的。

PIPE_NOWAIT的建议不被Microsoft推荐。

使用重叠的I / O。 然后,WriteFile()将总是立即返回,如果数据没有立即写入管道,将返回FALSE和ERROR_IO_PENDING。 在这种情况下,您可以调用CancelIo()来取消尝试的WriteFile()。 请记住,调用CancelIo()之后,必须调用GetOverlappedResult(),因为重叠的WriteFile()仍然需要完成 – 即使它将会失败,并且如果在释放之前释放了OVERLAPPED结构,将会导致堆栈损坏。

顺便说一句,你应该接受这个问题的答案。 你问了一年多了!