FILE_FLAG_WRITE_THROUGH 和 FILE_FLAG_NO_BUFFERING的区别

本文详细解释了在使用CreateFile()函数时,FILE_FLAG_WRITE_THROUGH 和 FILE_FLAG_NO_BUFFERING两个标志的作用。FILE_FLAG_WRITE_THROUGH确保写入操作直接将数据写入文件而不经过缓存,而FILE_FLAG_NO_BUFFERING则进一步消除了所有读取预缓存,确保所有读取都直接来自文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

INFO: FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING

Summary

The FILE_FLAG_WRITE_THROUGH flag for CreateFile() causes any writes made to that handle to be written directly to the file without being buffered. The data is cached (stored in the disk cache); however, it is still written directly to the file. This method allows a read operation on that data to satisfy the read request from cached data (if it's still there), rather than having to do a file read to get the data. The write call doesn't return until the data is written to the file. This applies to remote writes as well--the network redirector passes the FILE_FLAG_WRITE_THROUGH flag to the server so that the server knows not to satisfy the write request until the data is written to the file.


The FILE_FLAG_NO_BUFFERING takes this concept one step further and eliminates all read-ahead file buffering and disk caching as well, so that all reads are guaranteed to come from the file and not from any system buffer or disk cache. When using FILE_FLAG_NO_BUFFERING, disk reads and writes must be done on sector boundaries, and buffer addresses must be aligned on disk sector boundaries in memory.


These restrictions are necessary because the buffer that you pass to the read or write API is used directly for I/O at the device level; at that level, your buffer addresses and sector sizes must satisfy any processor and media alignment restrictions of the hardware you are running on.

More Information

The Windows 95 CDFS (CD-ROM File System) does not support the FILE_FLAG_NO_BUFFERING flag for CreateFile(). While a Windows 95 FSD, such as VFAT, may implement it, FILE_FLAG_NO_BUFFERING is not a required flag for file system drivers, and it is not supported by CDFS.


This code fragment demonstrates how to sector-align data in a buffer and pass it to CreateFile():

  char buf[2 * SECTOR_SIZE - 1], *p;

p = (char *) ((DWORD) (buf + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1));
h = CreateFile(argv[1], GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL);
WriteFile(h, p, SECTOR_SIZE, &dwWritten, NULL);

The pointer p is sector-aligned and points within the buffer.


If you have a situation where you want to flush all open files on the current logical drive, this can be done by:

   hFile = CreateFile("\\\\.\\c:", ....);
FlushFileBuffers(hFile);
This method causes all buffered write data for all open files on the C: partition to be flushed and written to the disk. Note that any buffering done by anything other than the system is not affected by this flush; any possible file buffering that the C Run-time is doing on files opened with C Run-time routines is unaffected.


When opening a remote file over the network, the server always caches and ignores the no buffering flag specified by the client. This is by design. The redirector and server cannot properly implement the full semantics of FILE_FLAG_NO_BUFFERING over the network. In particular, the requirement for sector-sized, sector-aligned I/O cannot be met. Therefore, when a Win32- based application asks for FILE_FLAG_NO_BUFFERING, the redirector and server treat this as a request for FILE_FLAG_WRITE_THROUGH. The file is not cached at the client, writes go directly to the server and to the disk on the server, and the read/write sizes on the network are exactly what the application asks for. However, the file is cached on the server.


Not caching the client can have a different effect, depending on the type of I/O. You eliminate the cache hits or read ahead, but you also may reduce the size of transmits and receives. In general, for sequential I/O, it is a good idea to cache on the client. For small, random access I/O, it is often best not to cache.


此文复制msdn:https://support.microsoft.com/en-us/help/99794/info-file-flag-write-through-and-file-flag-no-buffering

<think>好的,我现在需要解决用户在使用Windows API的WriteFile函数写磁盘时遇到错误代码5的问题。错误代码5代表“访问被拒绝”,这说明程序在尝试写入磁盘时权限不足或者有其他访问限制。首先,我应该回忆一下Windows系统中文件磁盘写入权限的相关知识。 用户提到使用的是C++Windows API,所以可能涉及到权限提升的问题。在Windows中,普通应用程序默认以标准用户权限运行,而直接写入磁盘可能需要管理员权限。因此,解决方案可能包括以管理员身份运行程序。这时候,用户需要修改程序清单文件,添加请求管理员权限的声明,或者直接以管理员身份启动应用程序。参考引用[3]提到了CreateFile等API,可能需要检查打开磁盘句柄时的访问权限参数是否正确。 其次,磁盘设备的访问模式也很重要。使用CreateFile打开物理驱动器或卷时,必须指定正确的访问标志。例如,GENERIC_WRITEFILE_SHARE_WRITE可能需要在dwDesiredAccessdwShareMode参数中设置。如果参数不正确,会导致访问被拒绝。此外,打开磁盘设备时可能需要使用特定的设备名称格式,比如\\.\PhysicalDrive0,这部分是否正确? 另外,错误处理方面,用户需要确认是否在调用WriteFile之前成功获取了有效的句柄。如果CreateFile失败,后续的WriteFile自然会失败。此时应该检查CreateFile的返回值,并调用GetLastError来获取具体的错误信息。例如,如果CreateFile返回INVALID_HANDLE_VALUE,错误代码可能同样提示权限问题或路径错误。 还有,需要考虑系统策略或安全软件的影响。某些情况下,防病毒软件或组策略可能会阻止直接磁盘写入操作。暂时禁用这些软件或调整策略可能有助于排查问题。此外,磁盘是否被其他进程独占打开?比如,如果另一个程序已经以独占模式打开了磁盘句柄,那么当前程序的写入请求会被拒绝。需要确保没有其他进程占用磁盘。 根据引用[2],用户可能在字符编码方面遇到问题,但此处错误代码5更多是权限问题,而不是编码问题。不过,确认传递给API的字符串是否正确也是必要的,比如设备路径是否使用宽字符(LPCWSTR),在Unicode环境下是否正确使用了_T()宏或L前缀。 总结可能的解决步骤:1. 以管理员身份运行程序;2. 检查CreateFile的参数是否正确,特别是访问权限共享模式;3. 确认设备路径正确;4. 确保没有其他进程占用磁盘;5. 处理可能的防软件干扰;6. 检查错误处理逻辑是否正确获取错误代码。最后,建议用户逐步排查这些方面,确保每个环节都正确配置。</think>### 解决 WriteFile 写磁盘错误代码 5 的步骤 错误代码 5 表示 `ACCESS_DENIED`(访问被拒绝),通常由权限不足或资源访问冲突引起。以下是针对 Windows API(C++)的解决方案: --- #### 1. **以管理员权限运行程序** - **问题**:普通应用程序默认不具备直接写入磁盘的权限。 - **解决方案**: - 在程序清单文件(`.manifest`)中添加管理员权限请求: ```xml <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/> ``` - 或直接以管理员身份运行编译后的程序。 --- #### 2. **检查 CreateFile 的参数** - **问题**:打开磁盘句柄时未正确设置访问权限或共享模式。 - **解决方案**:确保调用 `CreateFile` 时参数如下: ```cpp HANDLE hDevice = CreateFile( L"\\\\.\\PhysicalDrive0", // 磁盘设备路径(例如 PhysicalDrive0) GENERIC_WRITE, // 需要写入权限 FILE_SHARE_WRITE, // 允许其他进程写入共享 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); ``` - 若句柄无效(`hDevice == INVALID_HANDLE_VALUE`),调用 `GetLastError()` 进一步排查[^3]。 --- #### 3. **验证设备路径格式** - **问题**:设备路径格式错误可能导致打开失败。 - **解决方案**: - 使用宽字符格式(`L"\\\\.\\PhysicalDrive0"`)避免字符编码问题[^2]。 - 确认目标磁盘的编号(例如 `PhysicalDrive0` 表示第一块物理磁盘)。 --- #### 4. **检查磁盘占用与锁定** - **问题**:其他进程或系统已锁定磁盘。 - **解决方案**: - 关闭可能占用磁盘的程序(如资源管理器、杀毒软件)。 - 尝试卸载磁盘卷(需管理员权限): ```cpp DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, ...); // 锁定卷 DeviceIoControl(hDevice, FSCTL_DISMOUNT_VOLUME, ...); // 卸载卷 ``` --- #### 5. **绕过文件系统直接写入(谨慎操作)** - **问题**:文件系统限制导致写入失败。 - **解决方案**: - 使用 `FILE_FLAG_NO_BUFFERING` `FILE_FLAG_WRITE_THROUGH` 标志绕过缓存: ```cpp HANDLE hDevice = CreateFile(..., FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, ...); ``` - 确保写入数据的对齐方式符合磁盘要求(通常为 512 字节或 4KB)。 --- #### 6. **处理防病毒软件或组策略限制** - **问题**:安全软件或组策略阻止直接磁盘写入。 - **解决方案**: - 临时禁用防病毒软件。 - 检查组策略中是否限制了对磁盘的底层访问。 --- ### 示例代码片段 ```cpp #include <windows.h> #include <iostream> int main() { HANDLE hDisk = CreateFile( L"\\\\.\\PhysicalDrive0", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hDisk == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); std::cerr << "CreateFile failed, error: " << err << std::endl; return 1; } // 准备写入数据(需按磁盘扇区对齐) char buffer[512] = {0}; DWORD bytesWritten; if (!WriteFile(hDisk, buffer, sizeof(buffer), &bytesWritten, NULL)) { DWORD err = GetLastError(); std::cerr << "WriteFile failed, error: " << err << std::endl; CloseHandle(hDisk); return 1; } CloseHandle(hDisk); return 0; } ``` --- ### 注意事项 - **数据安全性**:直接写入物理磁盘可能破坏文件系统,建议在虚拟环境或测试磁盘中操作。 - **错误代码扩展**:通过 `FormatMessage` 函数将错误代码转换为可读信息: ```cpp LPSTR errMsg = nullptr; FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errCode, 0, (LPSTR)&errMsg, 0, NULL); std::cerr << "Error: " << errMsg << std::endl; LocalFree(errMsg); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值