Я с трудом определяю, как лучше всего реализовать fsync () в системе реального времени. Единственное требование, которое мне нужно выполнить, это то, что fsync () не должен разбивать кадры (100 Гц — 10 мс на кадр). Я провел некоторые начальные тесты, и в настоящее время я склоняюсь к вызову fsync () после каждой записи фиксированного размера (около 1 КБ), пока файл не будет завершен. Другое предложение, которое мне было дано, — это вызов fsync () для более медленной задачи / потока (либо в конце всего файла, либо в каждом кадре этой более медленной задачи).
Вы можете догадаться, что я новичок в этом, по тому, как я описал проблему и варианты, которые я исследовал, но все равно ударил меня сложными вещами. Есть ли другая реализация, которую я могу попробовать? Какой самый эффективный / лучший способ сделать это?
Спасибо!
Отредактировано: ОС, на которой я работаю — Linux. Для выполнения записи я использую библиотеку C с FILE * для выполнения файлового ввода-вывода. Поскольку в настоящее время это происходит для задачи 100 Гц, это 100 кадров в секунду с записью 1 КБ на кадр (это только для этой конкретной операции и не учитывает другие записи, происходящие в других местах этого кадра другими операторами).
Вы действительно должны дать конкретную информацию о том, какую операционную систему вы используете, чтобы получить хороший ответ на этот вопрос. Большинство Unix-подобных ОС не имеют понятия гарантий в реальном времени, а те, которые действительно имеют очень утраченные гарантии относительно файлового ввода / вывода.
В оставшейся части этого ответа я собираюсь предположить, что вы используете какой-то вариант современного Linux, который имеет некоторые ограниченные функции планирования в реальном времени. Я также собираюсь предположить, что вы записываете данные в простой файл в стандартной файловой системе (ext [234], btrfs и т. Д.). Я также собираюсь предположить, что вы используете низкоуровневые системные вызовы read () / write (), а не буферизацию на уровне приложений с использованием C-stdio или C ++ iostreams …
При проектировании уровней файловой системы Linux все операции ввода-вывода на дисках и с дисков кэшируются в памяти и асинхронно распределяются в аппаратном хранилище по мере необходимости. Существует поток ядра, который периодически сбрасывает грязные страницы в памяти на диск в течение настраиваемого интервала, и этот интервал является настраиваемым, изменяемым с помощью sysctl
или /proc/sys
интерфейс. При небольших нагрузках ввода / вывода эта асинхронная схема более чем достаточна для того, чтобы гарантировать, что ваши процессы не будут долго блокироваться при вводе / выводе, но поскольку ваша нагрузка ввода / вывода начинает превышать объем, который может быть физически записан на диск, Ваше приложение будет заблокировано, и это может быть очень длительной операцией.
То, что вы делаете с вашими вызовами fsync (), обходит асинхронные механизмы ядра для амортизации стоимости ввода-вывода, гарантируя, что грязные страницы, которые вы создаете, сбрасываются до завершения вашей операции ввода-вывода. Если вы делаете это со слишком маленьким размером набора ввода / вывода, вы, на самом деле, нелогично делаете ввод / вывод намного медленнее.
Предполагая, что ваша оценка для типичного размера ввода / вывода составляет 1 КБ на кадр, и предположив, что ~ 30-60 кадров в секунду является правильным, я считаю, что это будет где-то между 30-60 КБ в секунду, что должно быть в пределах способности ОС записывать данные на диск самостоятельно. В связи с этим я советую вам просто бросить банку и позаботиться о блокировке ввода-вывода, если это станет проблемой. Однако я бы также потратил некоторое время на написание некоторого кода, который измеряет время, потраченное на системный вызов write, и измеряет его, чтобы быть уверенным 🙂
Других решений пока нет …