LINUX.ORG.RU

Эмуляция O_DIRECT


0

0

Короче, Линус сказал, что O_DIRECT - это плохо и неправильно
(http://lkml.org/lkml/2007/1/10/233), посему у меня вопрос: как это
делать правильно сэмулировать на posix_fadvise? Требуется сделать так,
чтобы ядро НЕ кэшировало файл при его чтении.

Следующий код не работает:

if ((fd_in = open64(argv[1], O_RDONLY | O_LARGEFILE)) == -1) {
printf("Error: source file can't be open\n");
perror("open() ");
return 3;
}

posix_fadvise(fd_in, 0, filesize(argv[1]), POSIX_FADV_NOREUSE);

Далее файл читается в память, но ядро всё равно забивает пямять его
кэшем.

Зато работает следующий код:

if ((fd_in = open64(argv[1], O_RDONLY | O_LARGEFILE | O_DIRECT)) == -1) {
printf("Error: source file can't be open\n");
perror("open() ");
return 3;
}


(filesize можно заменить на 0 на ядрах > 2.6.6)

★★★★★

Да, я бы с удовольствием забил на Линуса, но O_DIRECT не реализован на некоторых файловых системах (например vfat aka fat32).

birdie ★★★★★
() автор топика
Ответ на: комментарий от fghj

# echo 1 > /proc/sys/vm/drop_caches

код:

posix_fadvise(fd_in, 0, filesize(argv[1]), POSIX_FADV_DONTNEED);

читаю весь файл, смотрю вывод top - весь файл оказался в кеше

birdie ★★★★★
() автор топика
Ответ на: комментарий от birdie

>posix_fadvise(fd_in, 0, filesize(argv[1]), POSIX_FADV_DONTNEED);

эта программа даже не скомпилируется,
posix_fadvise вызывается до или после чтения?

fghj ★★★★★
()
Ответ на: комментарий от birdie

>> Линус говорил о madvise

> Т.е. предлагаете mmap'ить файл?

Предлагаю попробовать. Альтернативно - предлагаю вызывать posix_fadvise так - прочитал кусок файла, вызывал _для прочитанного куска_. Если posix_fadvise и работает, то работает оно на содержимом страничного кэша, а при вызове сразу после открытия файла страничный кэш для него еще пуст.

> Иначе никак?

Не знаю. Линус выражался туманно.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Альтернативно - предлагаю вызывать posix_fadvise так - прочитал кусок файла, вызывал _для прочитанного куска_.

А смысл? файл уже в кеше

Короче, надо попробовать с mmap'ом

birdie ★★★★★
() автор топика
Ответ на: комментарий от birdie

>> Альтернативно - предлагаю вызывать posix_fadvise так - прочитал кусок файла, вызывал _для прочитанного куска_.

>А смысл?

Смысл в том, чтобы следующий кусок лег на это же место в кэше

> файл уже в кеше

Не весь, а только прочитанный кусок

tailgunner ★★★★★
()
Ответ на: комментарий от birdie

>http://anvil.perm.ru/files/sfcp4.2.c

как-то абсолютно нелогично fadvise используется,
сначала говорите не нужно:
posix_fadvise(fd_in, 0, filesize(argv[1]), POSIX_FADV_DONTNEED);
а потом
bytes_read = read(fd_in, (void *) buffer, BUFFER);

надо делать наоборот,
по аналогии выделил память - освободил.

fghj ★★★★★
()
Ответ на: комментарий от fghj

а для копирования можно использовать splice наверное,
так будет быстрее.
и вызывать posix_fadvise после.

fghj ★★★★★
()
Ответ на: комментарий от fghj

> а для копирования можно использовать splice наверное, так будет быстрее. и вызывать posix_fadvise после.

у меня glibc старый :(

man splice

No manual entry for splice

birdie ★★★★★
() автор топика
Ответ на: комментарий от birdie

Хотя это вопрос и не ко мне :), но всё же: поставь оба вызова posix_fadvise в цикле после вызовов read.

PS splice тебе не нужен - ты же не копируешь файлы, а сравниваешь их, так?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> PS splice тебе не нужен - ты же не копируешь файлы, а сравниваешь их, так?

Эта программулька сначала копирует, потом сравнивает.

birdie ★★★★★
() автор топика
Ответ на: комментарий от birdie

Круглосуточный DevSupport @ LOR: всегда рады помочь!

8)

tailgunner ★★★★★
()

И всё же непонятно, почему posix_fadvise надо вызывать после чтения и что тогда реально значит третий параметр у этой функции.

birdie ★★★★★
() автор топика
Ответ на: комментарий от birdie

posix_fadvise - это функция управления вытеснением данных из страничного кэша. Почему после чтения - потому что до него страничный кэш пустой (как правильно сказал fghj: "выделил память - освободил"). Третий параметр указывает, как именно вытеснять указанные страницы (POSIX_FADV_DONTNEED - заменять указанные страницы новыми при первой возможности).

Вышеприведенное не претендует на корректность в рамках любой POSIX-системы - это мое понимание реализации в Linux.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

#define _XOPEN_SOURCE 600
#include <fcntl.h>

int posix_fadvise(int fd, off_t offset, off_t len, int advice);

Третий параметр - это off_t len (значение, которого мне не столь понятно), значение advice более менее само по себе ясно.

birdie ★★★★★
() автор топика
Ответ на: комментарий от birdie

> Третий параметр - это off_t len (значение, которого мне не столь понятно), значение advice более менее само по себе ясно.

Прохлопал ;( 3-й параметр вкупе со 2-м указывают, на какие страницы распространяется указанный метод вытеснения страниц из кэша.

tailgunner ★★★★★
()
Ответ на: комментарий от birdie

ИМХО, потому что posix_fadvise действует на содержимое страничного кэша - новый вызов read заполняет кэш новым содержимым, поэтому нужен новый вызов posix_fadvise.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.