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 スケジューリングの問題ですか、それとも私が何かを見逃したのでしょうか? そして、どうすればこの問題を解決できますか?

ありがとう。

更新:

クリストフの提案によると、コードを作り直したところ、次のようになりました。

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 の実装を見ると、決して (まあまあ、1 回) は呼び出されないことがわかりますwrite_one_page()。大規模なデータ転送の場合は、mpage_writepages()代わりに使用します。

これは、ハードウェアにすぐにアクセスするのではなく、ブロック I/O インターフェイスを使用します。これは、IO スケジューラを通過することを意味します。大規模な操作がシステム全体をブロックすることはありません。スケジューラは、他の操作が大規模な書き込みにインターリーブされることを自動的に保証するためです。

于 2012-05-23T15:03:33.000 に答える