Я пишу программное обеспечение для Linux, которое будет активно работать с пользовательскими файлами в фоновом режиме одновременно с другими приложениями, которые я не контролирую. Я хочу, чтобы мое фоновое приложение не перезаписывало изменения, внесенные другими приложениями. Но есть проблема - в отличие от Windows Linux не предоставляет возможности обязательной блокировки файлов, что создает возможность испортить работу пользователя из-за условий гонки, которых я бы хотел избежать.
Поэтому мне интересно - доступны ли в Linux файловые системы, которые предоставляют какие-то механизмы синхронизации, такие как операция сравнивать и менять местами, транзакции по принципу "все или ничего", обязательная блокировка файлов (как в Windows)?
@MaximEgorushkin, «Я хочу, чтобы он не перезаписывал изменения, сделанные пользователем» - мало?
У этой постановки задачи есть простое решение: записать в новые файлы.
Пользовательские процессы могут использовать буферизованный ввод-вывод (например, функции stdio), так что пользовательские записи могут быть отложены в буферах пользовательского пространства. Но файловый обозреватель не может этого знать. Ваша проблема, как указано, не имеет решения.
См. Обязательная блокировка файлов в Linux
@MaximEgorushkin, меня больше беспокоит сценарий, когда пользователь очищает буфер и закрывает файл, но мое приложение перезаписывает файл, делая изменения, сделанные пользователем безвозвратно. Ситуация, которую вы описали, меня меньше беспокоит, потому что большинство текстовых редакторов умеют определять, когда открытый файл изменяется на диске.





Переименование атомарно. Ваше приложение должно сравнить «eTags» источника и назначения (возможно, с соответствующими блокировками), прежде чем принимать решение о вызове метода rename ().
Ключевым моментом для меня является возможность compare-and-swap.
Файловые системы не обеспечивают сравнение и обмен на основе атрибутов файлов. Ваша программа должна это делать. Также см. stackoverflow.com/questions/28417765/…
ммм, я не уверен, что это возможно. Надеюсь, у кого-то есть ответ.
Я поддерживаю этот ответ, потому что ваш вопрос потенциально имеет чрезвычайно сложные варианты использования и множество углов, но ключ к ответу на него заключается в том, чтобы сделать окончательную запись в файл атомарной, и никто другой не заявил об этом. Имея атомарный метод для замены, вы можете записывать во временные местоположения, сравнивать временные метки и сопоставлять изменения в вашей программе; вам не нужно беспокоиться о блокировке записи или повреждении окончательного файла. Если вам нужна блокировка чтения для обновления, вам понадобится база данных.
Общие ресурсы требуют защиты от одновременного доступа, потому что, если несколько потоков выполнения обращаются и манипулируют данными одновременно, потоки могут перезаписывать изменения друг друга или получать доступ к данным, пока они находятся в несогласованном состоянии. Одновременный доступ к общим данным - это рецепт нестабильности, который часто бывает очень сложно отследить и отладить - важно получить это сразу же [1]
Потоки могут использовать следующие два инструмента для синхронизации своих действий: мьютексы и условные переменные [2]
Мьютексы (сокращение от взаимного исключения) позволяют потокам синхронизировать использование общего ресурса, так что, например, один поток не пытается получить доступ к общей переменной одновременно с тем, как другой поток изменяет ее.
Переменные условия выполняют дополнительную задачу: они позволяют потокам сообщать друг другу, что общая переменная (или другой общий ресурс) изменила состояние.
Адаптировано из:
[1] Любовь, Р. (2005). Разработка ядра Linux, второе издание.
[2] Керриш, М. (2010). Программный интерфейс Linux.
Имейте в виду, что я ищу решение для синхронизации работы с файлами в нескольких независимых приложениях, а не только в моем приложении.
Вопрос требует ясности.
Я считаю, что есть три возможных решения
1) Сделайте так, чтобы все программы использовали настраиваемую библиотеку ввода-вывода файлов, которая реализует необходимые вам функции. Это решение может оказаться невозможным, если у вас нет доступа к исходному коду. Вы также можете рассмотреть возможность использования mmap, чтобы изменения записывались в память. Вы используете фоновый процесс для синхронизации грязных страниц с существующими или новыми файлами.
2) Заменить стандартные библиотеки C / C++ (например, libc.so), которые будут использовать затронутые программы. Вы можете использовать ldd, чтобы узнать зависимость библиотеки. Вам необходимо обновить исходный код для стандартного C / C++, чтобы реализовать необходимые вам функции. Для большинства людей это может быть слишком сложно.
3) Создайте свою файловую систему. Вы можете сослаться на множество статей в Интернете, например, https://kukuruku.co/post/writing-a-file-system-in-linux-kernel/. Это лучшее и самое чистое решение.
Надеюсь, это поможет.
Думаю, я выберу вариант 3) - напишу оболочку над обычной файловой системой с FUSE, которая добавит обязательную функцию блокировки или операцию CAS.
Кажется, что у mmap есть такая защита, которую вы ищете: https://www.kernel.org/doc/html/v4.13/media/uapi/v4l/func-mmap.html
prot The prot argument describes the desired memory protection. Regardless of the device type and the direction of data exchange it should be set to PROT_READ | PROT_WRITE, permitting read and write access to image buffers. Drivers should support at least this combination of flags.
Вы пропустили постановку проблемы. Что именно ты пытаешься сделать?