如何在linux内核中禁用页面缓存?

时间:2016-06-18 02:53:08

标签: linux caching linux-kernel fuse glusterfs

如何避免内核中的页面缓存,应用程序可以直接从磁盘写入或读取数据?在内核中,如何设置?

2 个答案:

答案 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 设备只有保证写页面启用/禁用开关,

SATA

参考 sata 3.0 规范:

<块引用>

SET FEATURES (Write Cache Enable/Disable):写缓存启用/禁用设置 由 SET FEATURES 命令建立,子命令代码为 02h 或 82h。

linux内核下,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");
            }
        }

NVME

内核源:

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;
}

nvme 规范:

enter image description here