Как синхронизировать ввод/вывод файлов из многих независимых приложений в Linux?

Я пишу программное обеспечение для Linux, которое будет активно работать с файлами пользователя в фоновом режиме одновременно с другими приложениями, которые я не контролирую. Я хочу, чтобы мое фоновое приложение не перезаписывало изменения, сделанные другими приложениями. Но есть проблема - в отличие от Windows Linux не обеспечивает обязательной блокировки файлов, что создает возможность разрушить работу пользователя из-за условий гонки, которых я бы хотел избежать.

Поэтому мне интересно - существуют ли в Linux файловые системы, которые предоставляют какие-то механизмы синхронизации, такие как операция сравнения и замены, транзакции "все или ничего", принудительная блокировка файлов (например, в Windows)?

Ответ 1

Я считаю, что существует три возможных решения

1) Сделать все программы для использования пользовательской библиотеки ввода-вывода файлов, которые реализуют необходимые функции. Это решение может оказаться невозможным, если у вас нет доступа к исходному коду. Вы также можете использовать mmap, чтобы изменения записывались в память. Вы используете фоновый процесс для синхронизации грязных страниц с существующими или новыми файлами.

2) Замените стандартные библиотеки C/C++ (например, libc.so), которые будут влиять на программы. Вы можете использовать ldd для поиска зависимости от библиотеки. Вам необходимо обновить исходный код для стандартного C/C++, чтобы реализовать нужные функции. Это может быть слишком сложно для большинства людей.

3) Создайте свою файловую систему. Вы можете ссылаться на многие статьи в Интернете, например https://kukuruku.co/post/writing-a-file-system-in-linux-kernel/. Это лучшее и чистое решение.

Надеюсь, поможет.

Ответ 2

Переименование - атомное. Перед тем, как принять решение о вызове rename(), вы можете сравнить "eTags" источника и адресата (возможно, под соответствующими блокировками).

Ответ 3

Общие ресурсы требуют защиты от параллельного доступа, потому что, если несколько потоков выполнения доступа и одновременно обрабатывают данные, потоки могут перезаписывать друг друга или получать доступ к данным, когда они находятся в противоречивом состоянии. Параллельный доступ к общим данным - это рецепт нестабильности, который часто оказывается очень трудным для отслеживания и отладки - получение его с места в карьер важно [1]

Темы могут использовать следующие два инструмента для синхронизации своих действий: мьютексы и переменные условия [2]

Мьютексы (сокращение от взаимного исключения) позволяют потокам синхронизировать использование общего ресурса, так что, например, один поток не пытается получить доступ к общей переменной одновременно с изменением другого потока.

Переменные условия выполняют дополнительную задачу: они позволяют потокам сообщать друг другу, что общая переменная (или другой общий ресурс) изменила состояние.

Адаптированы из:

[1] Любовь, Р. (2005). Linux Kernel Development, второе издание.

[2] Керриш, М. (2010). Интерфейс программирования Linux.

Ответ 4

mmap, похоже, обладает такой защитой, которую вы ищете: https://www.kernel.org/doc/html/v4.13/media/uapi/v4l/func-mmap.html

prot Аргумент prot описывает требуемую защиту памяти. Независимо от типа устройства и направления обмена данными, он должен быть установлен на PROT_READ | PROT_WRITE, разрешая доступ на чтение и запись к буферам изображений. Водители должны поддерживать по крайней мере это сочетание флагов.