0

看来我的 Linux IO 性能有问题。使用一个项目我需要clear从内核空间中完整的文件。我使用以下代码模式:

for_each_mapping_page(mapping, index) {
    page = read_mapping_page(mapping, index);
    lock_page(page);
    { kmap // memset // kunmap }
    set_page_dirty(page);
    write_one_page(page, 1);
    page_cache_release(page);
    cond_resched();
}

一切正常,但对于大文件(对我来说约为 3Gb+)我发现我的系统以一种奇怪的方式停止:虽然此操作未完成,但我无法运行任何东西。换句话说,在此操作之前存在的所有进程都运行良好,但是如果我在此操作期间尝试运行某些东西,在它完成之前我什么也看不到。

是内核的 IO 调度问题还是我错过了什么?我该如何解决这个问题?

谢谢。

升级版:

根据 Kristof 的建议,我重新编写了代码,现在看起来像这样:

headIndex = soff >> PAGE_CACHE_SHIFT;
tailIndex = eoff >> PAGE_CACHE_SHIFT;

/**
 * doing the exact @headIndex .. @tailIndex range
 */

for (index = headIndex; index < tailIndex; index += nr_pages) {
    nr_pages = min_t(int, ARRAY_SIZE(pages), tailIndex - index);

    for (i = 0; i < nr_pages; i++) {
        pages[i] = read_mapping_page(mapping, index + i, NULL);
        if (IS_ERR(pages[i])) {
            while (i--)
                page_cache_release(pages[i]);
            goto return_result;
        }
    }

    for (i = 0; i < nr_pages; i++)
        zero_page_atomic(pages[i]);

    result = filemap_write_and_wait_range(mapping, index << PAGE_CACHE_SHIFT,
                          ((index + nr_pages) << PAGE_CACHE_SHIFT) - 1);

    for (i = 0; i < nr_pages; i++)
        page_cache_release(pages[i]);

    if (result)
        goto return_result;

    if (fatal_signal_pending(current))
        goto return_result;

    cond_resched();
}

结果,我获得了更好的 IO 性能,但是在导致操作的同一用户中进行并发磁盘访问时,仍然存在大量 IO 活动的问题。

无论如何,感谢您的建议。

4

1 回答 1

3

本质上,您完全绕过了内核 IO 调度程序。

如果您查看 ext2 实现,您会看到它 never (well ok, once) calls write_one_page()。对于大规模数据传输,它mpage_writepages()改为使用。

这使用块 I/O 接口,而不是立即访问硬件。这意味着它通过 IO 调度程序。大型操作不会阻塞整个系统,因为调度程序会自动确保其他操作与大型写入交错。

于 2012-05-23T15:03:33.000 回答