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

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

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

Вы пропустили постановку проблемы. Что именно ты пытаешься сделать?

Maxim Egorushkin 25.09.2018 13:59

@MaximEgorushkin, «Я хочу, чтобы он не перезаписывал изменения, сделанные пользователем» - мало?

Gill Bates 25.09.2018 15:01

У этой постановки задачи есть простое решение: записать в новые файлы.

Maxim Egorushkin 25.09.2018 15:57

Пользовательские процессы могут использовать буферизованный ввод-вывод (например, функции stdio), так что пользовательские записи могут быть отложены в буферах пользовательского пространства. Но файловый обозреватель не может этого знать. Ваша проблема, как указано, не имеет решения.

Maxim Egorushkin 25.09.2018 15:58

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

Gill Bates 26.09.2018 10:07
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
6
245
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Ключевым моментом для меня является возможность compare-and-swap.

Gill Bates 21.09.2018 08:38

Файловые системы не обеспечивают сравнение и обмен на основе атрибутов файлов. Ваша программа должна это делать. Также см. stackoverflow.com/questions/28417765/…

itisravi 21.09.2018 13:39
Ваша программа должна это делать. Мне нужна синхронизация не только внутри приложения, но и между всеми приложениями, которые обращаются к файловой системе.
Gill Bates 21.09.2018 14:21

ммм, я не уверен, что это возможно. Надеюсь, у кого-то есть ответ.

itisravi 22.09.2018 08:39

Я поддерживаю этот ответ, потому что ваш вопрос потенциально имеет чрезвычайно сложные варианты использования и множество углов, но ключ к ответу на него заключается в том, чтобы сделать окончательную запись в файл атомарной, и никто другой не заявил об этом. Имея атомарный метод для замены, вы можете записывать во временные местоположения, сравнивать временные метки и сопоставлять изменения в вашей программе; вам не нужно беспокоиться о блокировке записи или повреждении окончательного файла. Если вам нужна блокировка чтения для обновления, вам понадобится база данных.

joshstrike 30.09.2018 07:32

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

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

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

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

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

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

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

Имейте в виду, что я ищу решение для синхронизации работы с файлами в нескольких независимых приложениях, а не только в моем приложении.

Gill Bates 26.09.2018 10:03

Вопрос требует ясности.

Tiago Martins Peres 26.09.2018 10:52
Ответ принят как подходящий

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

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.

Gill Bates 29.09.2018 14:46

Кажется, что у 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.

Другие вопросы по теме