Как я могу синхронизировать два процесса, обращающихся к файлу на NAS?

StackOverflow https://stackoverflow.com/questions/472329

Вопрос

Вот в чем дело: у меня есть два приложения, написанные на C ++ и работающие на двух машинах с разными ОС (одна Linux и одна Windows). Один из этих процессов отвечает за обновление XML-файла на NAS (Network Attached Storage), в то время как другой читает этот файл.

Можно ли синхронизировать эти два процесса, чтобы избежать чтения файла во время его изменения?

Это было полезно?

Решение

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

Изменить . Чтобы учесть комментарии, вы можете реализовать двойную проверку шаблона типа блокировки. Пусть у читателя и писателя есть файл блокировки и двойная проверка, прежде чем вы начнете работать, что-то вроде:

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

Writer: проверьте файл блокировки чтения, создайте файл блокировки записи, проверьте файл блокировки чтения, если существует, удалите файл блокировки записи и отмените.

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

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

Спасибо всем за ваши ответы.

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

Хорошо, вам нужен механизм блокировки для контроля доступа.

Большинство * nix файловых систем обеспечивают это. Я подозреваю, что он также доступен в файловой системе Windows (так как этот механизм используется в Perl), но может иметь другое имя.

Посмотрите на стадо ().
Это механизм блокировки файлов. Это рекомендательная блокировка, поэтому она на самом деле не блокирует файл и не предотвращает его использование, но предоставляет механизм для маркировки файла. Если оба приложения используют этот механизм, вы можете контролировать доступ к файлу.

flock () предоставляет как общие блокировки (или блокировку READ), так и эксклюзивные блокировки (или блокировку WRITE). flock будет блокировать ваш поток (не занятым способом), пока файл не будет разблокирован пользователем (он также обеспечивает НЕ блокирующие проверки, чтобы вы могли делать другие вещи во время ожидания).

Ознакомьтесь с паствой в разделе 2 справочных страниц.

int     flock(int fd, int operation);

Flock() applies or removes an advisory lock on the file associated with the file
descriptor fd.  A lock is applied by specifying an operation parameter that is
one of LOCK_SH or LOCK_EX with the optional addition of LOCK_NB.  To unlock an
existing lock operation should be LOCK_UN.

Если файлы находятся в общей папке NFS, вы можете использовать fcntl (2) чтобы заблокировать файл. Проверьте вопрос D10 в FAQ по NFS для Linux . У меня очень мало опыта работы с Windows API, но из того, что я слышал, у них хорошая поддержка POSIX, поэтому вы сможете использовать fcntl, если они поддерживают POSIX.1-2001.

Если вы обращаетесь к файлам по разным протоколам (например, AFS или SMB), возможно, вы могли бы настроить простой сервер синхронизации, который управляет блокировками через интерфейс IPC?

Можно ли переключаться с файлов на базу данных?

Этот тип параллелизма - это то, что СУБД управляют очень хорошо. Он не должен быть дорогим или сложным в установке. MySql, Postgress или JavaDB справятся с этим элегантно, за небольшую плату или бесплатно.

Если опция базы данных не сработает, процесс записи будет записан в " скрытый " имя файла, например " .updateinprogress.xml " и переименуйте файл, когда обновление будет завершено. На большинстве систем & Quot; mv & Quot; или " ren " это атомарная операция, поэтому процесс чтения забирает старый или новый файл, но никогда не записывает его наполовину.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top