Intereting Posts

Как я могу синхронизировать – делать атомарные записи в одном файле из двух процессов?

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

обрабатывающий буфер 1 записи, содержащий (A1, A2, A3) и буфер B записи процесса 2, включая (B1, B2, B3). когда мы используем системный вызов write() для записи этих буферов на диск в один и тот же файл (весь буфер за один раз: write(fd, A, sizeof(A)) ). Как схема файла?

  • Это так: A, B или B, может быть?
  • или это может быть так: A1, A2, B1, A3, …

Я спрашиваю об этом, потому что системные вызовы являются атомарными. что произойдет, если буфер данных, который мы пишем, слишком велик. Это как трубы для обычных файлов на диске?

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

Каждый вызов для write записывается в число запрошенных байтов. Если ваш процесс прерывается сигналом, вы можете получить частичную запись – возвращается фактическое количество записанных байтов. Получаете ли вы все свои байты или нет, вы написали один смежный раздел файла. Вы не получаете эффект перемежения, который вы упомянули, как свою вторую возможность (например, A1, B1, A2, B2, …).

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

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

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

Системный вызов записи является атомарным, да, это означает, что результатом будет либо A, либо B, а не смесь обоих.

Предполагая, что вы хотите как A, так и B в файле, вы можете открыть файл с помощью O_APPEND; Обратите внимание, что это не будет работать над NFS.

Другим вариантом является то, что каждый процесс отслеживает, какое смещение файла он должен использовать, и использует lseek () или pwrite ()

Вам определенно нужна некоторая форма синхронизации для ваших программ, которые обращаются к файлу, или вы в конечном итоге перепутали содержимое файла. Системный вызов записи может писать меньше байтов, чем вы просили, поэтому ваши блоки A1, A2 или B1, B2 могут быть записаны только частично. Это может происходить часто или редко, в зависимости от многих условий. Если это происходит только один раз в неделю, у вас будет ошибка, которую может быть очень сложно обнаружить.

В качестве решения вы можете использовать блокировку файлов ( man 2 flock или man fcntl и поиск блокировки). Другая возможность – использовать семафоры ( man -k semaphore ) для синхронизации ваших программных записей или некоторых других форм IPC.