Windows 在使用文件\标志\写入\通过打开的句柄上调用时,WriteFile应在何时阻止?

Windows 在使用文件\标志\写入\通过打开的句柄上调用时,WriteFile应在何时阻止?,windows,winapi,ntfs,windows-nt,sata,Windows,Winapi,Ntfs,Windows Nt,Sata,在工作中,我们在Jenkins的帮助下,定期在几台构建机器上运行单元测试。其中一个单元测试通过打开一个带有file\u FLAG\u WRITE\u的文件,并对该文件进行数以万计的WriteFile调用。这与这个问题无关。在其中一台构建机器上,此测试经常超时。经过一番调查,发现根本原因是对WriteFile的每次调用都被阻塞(线程被关闭,稍后又被切换),这使得测试运行速度大大降低。奇怪的是,当在这台机器上手动启动测试时,WriteFile没有阻塞,因此测试没有超时 经过数小时的反复试验,我找到了

在工作中,我们在Jenkins的帮助下,定期在几台构建机器上运行单元测试。其中一个单元测试通过打开一个带有
file\u FLAG\u WRITE\u的文件,并对该文件进行数以万计的
WriteFile
调用。这与这个问题无关。在其中一台构建机器上,此测试经常超时。经过一番调查,发现根本原因是对
WriteFile
的每次调用都被阻塞(线程被关闭,稍后又被切换),这使得测试运行速度大大降低。奇怪的是,当在这台机器上手动启动测试时,
WriteFile
没有阻塞,因此测试没有超时

经过数小时的反复试验,我找到了一个“解决办法”:在受影响的机器上,如果Jenkins是使用任务调度器启动的,
WriteFile
被阻止的,如果是手动启动的,或者通过在启动文件夹中放置BAT文件来启动的,则不会被阻止。我认为我需要做更多的调查,所以我创建了一个最小的repo,一个小程序,它通过
打开一个带有
file\u FLAG\u WRITE\u的文件,并使用随机数据对其调用
WriteFile
。通过这种最小的复制,
WriteFile
会不断阻塞,无论我如何启动它。我真的很困惑,所以我在这里要求对这种行为做出任何解释。我在上面执行测试的所有机器都有SATA驱动器,具有默认设置(已启用写缓存和Windows写缓存刷新)

首先,对于我来说,
FILE\u FLAG\u WRITE\u THROUGH
应该做什么还不是100%清楚。互联网上的信息表明,一个特殊的标志被传递给设备,要求它在写操作后刷新缓存。根据(和其他一些人)的说法,这在当今已不再重要,因为大多数SATA驱动器出于性能原因都会默默地忽略此标志。在“应阻止或不应阻止”一侧,明确说明使用
文件标志\u WRITE\u-to
WriteFile
应阻止:

写入调用在数据写入文件之前不会返回


你知道我为什么看到这种奇怪的行为(前后不一致)吗?如何进一步调查?

它绕过了文件系统缓存。让您了解磁盘写入的实际成本。当它不得不与使用磁盘的任何其他进程(读写)竞争时,就会导致大量的头部搜索,这是你能做的最昂贵的事情。缓存对此进行了大量优化,按柱面顺序排列写操作。发生在背景中,所以你永远不会注意到。没有什么特别的事情发生,你必须增加超时时间。我想如果没有其他线程准备运行,Windows将保留在你线程的上下文中,因此你的线程将在操作完成后重新启动,而不需要等待分配另一个时间片。所以我猜“奇数机器”运行的是CPU受限的其他东西,或者类似的东西。IIRC前台任务的优先级略高于后台任务,这可以解释手动运行时的差异——如果线程的优先级更高,则在I/O完成后,另一个线程将立即中断。。。。如果是这样,显式提高线程优先级可能会有所帮助。但这种情况偶尔也会发生,只要有更高优先级的东西在运行,因此Hans已经建议您可能需要编写测试来应对。@HarryJohnston我尝试在我的机器上运行优先级较低的单元测试(在这种情况下,我永远无法获得
WriteFile
,而这个特定的单元测试要阻止),并启动了一个重量级、高优先级的并行编译,该编译以高CPU负载运行8个工作进程(机器上有8个逻辑核)。单元测试运行速度明显较慢(但仍然没有超时),但是
WriteFile
即使在这个设置中也没有阻塞(通过WPA确认)。您如何确定调用是否阻塞?为了消除任何疑问,您没有使用异步I/O吗?