A
Android
Original poster
избегает дополнительной копии, которая происходит с буфером пространства пользователя при использовании чтения и записи
нет никаких системных вызовов для чтения из памяти
общий режим позволяет процессам обмениваться файлами
нет необходимости в lseek
mremap для изменения размера отображения
glib часто использует mremap для реализации realloc
mprotect поменять защиту отображения
msync для синхронизации изменений обратно на диск - всегда должен вызываться, потому что ядро не знает, что память была изменена, в отличие от грязных буферов записи
madvise, чтобы дать ядру подсказку об использовании карты - обычно это связано с количеством запросов на чтение (больше для последовательных, ни для случайных)
posix_fadvise очень похож, но для обычного ввода / вывода (не mmap)
Асинхронный ввод / вывод
* Здесь очень кратко. Следующие заметки взяты из справочной страницы aio (7)
* Интерфейс POSIX AIO состоит из следующих функций:
#include <aiocb.h>
aio_read (3) Поставить в очередь запрос на чтение. Это асинхронный аналог read (2).
aio_write (3) Поставить запрос на запись в очередь. Это асинхронный аналог write (2).
aio_fsync (3) Поставить запрос синхронизации для операций ввода-вывода для файлового дескриптора. Это асинхронный аналог fsync (2) и fdatasync (2).
aio_error (3) Получите состояние ошибки запроса ввода-вывода в очереди.
aio_return (3) Получить статус возврата завершенного запроса ввода / вывода.
aio_suspend (3) Приостановить вызывающую функцию до тех пор, пока не завершится один или несколько из указанного набора запросов ввода / вывода.
aio_cancel (3) Попытка отменить невыполненные запросы ввода-вывода для указанного файлового дескриптора.
lio_listio (3) Поставить в очередь несколько запросов ввода-вывода, используя один вызов функции.
struct aiocb {
int aio_fildes; / * Дескриптор файла * /
off_t aio_offset; / * Смещение файла * /
volatile void * aio_buf; / * Расположение буфера * /
size_t aio_nbytes; / * Длина перевода * /
int aio_reqprio; / * Запрос приоритета * /
struct sigevent aio_sigevent; / * Способ уведомления * /
int aio_lio_opcode; / * Операция должна быть выполнена;
};
* Вы можете либо опрашивать статус запроса (с помощью aio_error), либо завершить выдачу сигнала
* Вы можете попросить запрос сигнализировать через aiocbp-> aio_sigevent.sigev_notify = SIGEV_SIGNAL
* Вы также можете попросить его создать поток
* Если aio_error не EINPROGRESS, вы можете использовать aio_return, чтобы получить возвращаемое значение (например, соответствующей операции read ())
Планировщики ввода / вывода и производительность ввода / вывода
* Планировщик установлен в / sys / block / [device] / queue / scheduler
* Планировщик будет пытаться эффективно чередовать операции чтения и записи на диск
* Выполняет слияния (объединяет чтения в прилагательных блоках) и сортировку
* Поскольку записи передаются в потоковом режиме (асинхронно), они могут голодать при чтении (write-голодание-чтение)
Планировщик дедлайна
* хранит отсортированный список операций (отсортированный по физическому блоку)
* поддерживает очередь операций чтения FIFO и очередь операций записи FIFO
* чтение ops имеет срок 500 мс и запись ops 6s
* идет по отсортированному списку, если не наступает крайний срок, который получает приоритет
* Моя текущая машина с диском SSD NMVe использует mq-deadline (multiqueue)
Оптимизация ввода / вывода
* Есть много оптимизаций, которые можно сделать на стороне приложения:
* Минимизируйте операции ввода / вывода (объединение)
* Выполнить блок выровненных ввода-вывода
* Используйте буферизацию
* векторный ввод / вывод, позиционный ввод / вывод и асинхронный ввод / вывод
* Мы также можем сортировать запросы ввода / вывода перед отправкой их ядру
* Секторы сопоставляются с физическими блоками, поэтому хранилище блоков может быть адресовано блоками (адресация логических блоков, LBA) вместо цилиндров, головок и секторов.
* Файловые системы являются чисто программными, и говорят с точки зрения логических блоков
* Размер логического блока кратен размеру физического блока
* Сортировка пишет в приложении:
* Один из способов сделать это - путь -> плохое приближение
* Другой номер индекса -> разрывы с большей фрагментацией
* Или вы можете попробовать отсортировать по физическому блоку:
* Каждый файл разбит на логические блоки
* Вы можете получить физический блок из логического блока:
* ret = ioctl (fd, FIBMAP, & block);
*
* Логические блоки с нулевым индексом и относительными к файлам
* Сначала определите количество блоков в файле через fstat
* Затем для каждого логического блока найдите физический блок через ioctl.
* Поскольку файлы имеют тенденцию быть смежными, и мы в основном захотим упорядочить ввод-вывод для данного файла, просто используйте 0-й блок для сортировки:
* int logic_block = 0;
* ioctl (fd, FIBMAP, & logic_block);