Преимущества mmap

A

Android

Original poster
D8635991-114E-4E9B-AE03-FAE946E81740.png
избегает дополнительной копии, которая происходит с буфером пространства пользователя при использовании чтения и записи

нет никаких системных вызовов для чтения из памяти

общий режим позволяет процессам обмениваться файлами

нет необходимости в 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);