如何避免内核中的页面缓存,应用程序可以直接从磁盘写入或读取数据?在内核中,如何设置?
答案 0 :(得分:3)
您需要该应用程序才能调用O_DIRECT。从手册页http://man7.org/linux/man-pages/man2/open.2.html
有了这个,你告诉内核在进行I / O时不能从页面缓存中写入/读取。
O_DIRECT(自Linux 2.4.10起) 尝试最小化I / O的缓存效果 文件。一般来说,这会降低性能,但确实如此 在特殊情况下很有用,例如在应用程序执行时 他们自己的缓存。文件I / O直接与用户进行 - 空间缓冲区。 O_DIRECT标志本身就是一种努力 同步传输数据,但没有给出 保证O_SYNC标志该数据和必要的元数据 转移。为了保证同步I / O,O_SYNC必须是 除了O_DIRECT之外还使用。请参阅下面的注释 讨论
A semantically similar (but deprecated) interface for block
devices is described in raw(8).
答案 1 :(得分:0)
AFAIK,sata 和 nvme 设备只有保证写页面启用/禁用开关,
SET FEATURES (Write Cache Enable/Disable):写缓存启用/禁用设置 由 SET FEATURES 命令建立,子命令代码为 02h 或 82h。
HDIO_SET_WCACHE
ioctl可以控制:static DEFINE_MUTEX(ide_disk_ioctl_mutex);
static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
{ 0 }
};
int ide_disk_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
int err;
mutex_lock(&ide_disk_ioctl_mutex);
err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
if (err != -EOPNOTSUPP)
goto out;
err = generic_ide_ioctl(drive, bdev, cmd, arg);
out:
mutex_unlock(&ide_disk_ioctl_mutex);
return err;
}
hdparm -W0/1 /dev/sdx
方便地禁用/启用写入缓存,这也会在内部调用 HDIO_SET_WCACHE
:}
if (!wcache)
err = flush_wcache(fd);
if (ioctl(fd, HDIO_SET_WCACHE, wcache)) {
__u8 setcache[4] = {ATA_OP_SETFEATURES,0,0,0};
setcache[2] = wcache ? 0x02 : 0x82;
if (do_drive_cmd(fd, setcache, 0)) {
err = errno;
perror(" HDIO_DRIVE_CMD(setcache) failed");
}
}
static ssize_t queue_wc_show(struct request_queue *q, char *page)
{
if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
return sprintf(page, "write back\n");
return sprintf(page, "write through\n");
}
static ssize_t queue_wc_store(struct request_queue *q, const char *page,
size_t count)
{
int set = -1;
if (!strncmp(page, "write back", 10))
set = 1;
else if (!strncmp(page, "write through", 13) ||
!strncmp(page, "none", 4))
set = 0;
if (set == -1)
return -EINVAL;
if (set)
blk_queue_flag_set(QUEUE_FLAG_WC, q);
else
blk_queue_flag_clear(QUEUE_FLAG_WC, q);
return count;
}