在windows上,启用磁盘设备写缓存可以通过如下步骤实现:
“计算机”->“管理”->“设备管理器”->“磁盘驱动器”
选择需要修改的磁盘启动器,右击->“属性”,然后选择“策略”Tab页,如下图所示
启用磁盘设备写缓存后,如果直接拔出USB存储设备,可能导致文件数据丢失,需要通过安全删除硬件方式移除USB外置存储设备。
以下通过代码实现启用磁盘写缓存(搜索引擎很难搜索到相关内容,这里算是作为备忘录)
#define IOCTL_DISK_GET_CACHE_SETTING CTL_CODE(IOCTL_DISK_BASE, 0x0038, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DISK_SET_CACHE_SETTING CTL_CODE(IOCTL_DISK_BASE, 0x0039, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
typedef enum _DISK_CACHE_STATE {
DiskCacheNormal,
DiskCacheWriteThroughNotSuppoted,
DiskCacheModifyUnsuccessful,
}DISK_CACHE_STATE, *PDISK_CACHE_STATE;
typedef struct _DISK_CACHE_SETTING {
ULONG Version;
DISK_CACHE_STATE State;
BOOLEAN IsPowerProtected;
}DISK_CACHE_SETTING, *PDISK_CACHE_SETTING;
#define CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL 1
#define CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL 2
#define CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL 3
int enable_disk_write_cache(int disk_index)
{
int ret = -1;
unsigned long ret_bytes = 0;
wchar_t physical_path[MAX_PATH] = {0};
HANDLE file_handle = INVALID_HANDLE_VALUE;
DISK_CACHE_INFORMATION disk_cache_info = {0};
DISK_CACHE_SETTING disk_cache_setting = {0};
STORAGE_HOTPLUG_INFO storage_hotplug_info = {0};
wsprintfW(physical_path, L"\\\\.\\PhysicalDrive%d", disk_index);
do
{
file_handle = CreateFileW(physical_path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (file_handle == INVALID_HANDLE_VALUE)
{
break;
}
// 取消电源保护
if( DeviceIoControl(file_handle, IOCTL_DISK_GET_CACHE_SETTING, NULL, 0, &disk_cache_setting, sizeof(DISK_CACHE_SETTING), &ret_bytes, NULL) )
{
if (disk_cache_setting.IsPowerProtected)
{
disk_cache_setting.IsPowerProtected = FALSE;
if( !DeviceIoControl(file_handle, IOCTL_DISK_GET_CACHE_SETTING, NULL, 0, &disk_cache_setting, sizeof(DISK_CACHE_SETTING), &ret_bytes, NULL) )
{
// TODO:
}
}
}
// 启用更好的性能
storage_hotplug_info.Size = sizeof(STORAGE_HOTPLUG_INFO);
if( DeviceIoControl(file_handle, IOCTL_STORAGE_GET_HOTPLUG_INFO, NULL, 0, &storage_hotplug_info, sizeof(STORAGE_HOTPLUG_INFO), &ret_bytes, NULL ) )
{
if (storage_hotplug_info.DeviceHotplug)
{
storage_hotplug_info.Size = sizeof(STORAGE_HOTPLUG_INFO);
storage_hotplug_info.DeviceHotplug = FALSE;
if ( !DeviceIoControl(file_handle, IOCTL_STORAGE_SET_HOTPLUG_INFO, &storage_hotplug_info, sizeof(STORAGE_HOTPLUG_INFO), NULL, 0, &ret_bytes, NULL ))
{
// TODO:
}
}
}
// 启用磁盘写缓存
if (!DeviceIoControl(file_handle, IOCTL_DISK_GET_CACHE_INFORMATION, NULL, 0, &disk_cache_info, sizeof(DISK_CACHE_INFORMATION), &ret_bytes, NULL))
{
break;
}
if (!disk_cache_info.WriteCacheEnabled)
{
disk_cache_info.WriteCacheEnabled = TRUE;
if (!DeviceIoControl(file_handle, IOCTL_DISK_SET_CACHE_INFORMATION, &disk_cache_info, sizeof(DISK_CACHE_INFORMATION), NULL, 0, &ret_bytes, NULL))
{
break;
}
}
ret = 0;
} while (0);
if (file_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(file_handle);
}
return ret;
}