Является ли fwrite атомарным?

Простой вопрос:

Мне нужно добавить ведение журнала в мою программу.

Если два процесса используют «fwrite» для одного и того же файла, но с разными файловыми дескрипторами, записываемые сообщения журнала будут атомарными или смешанными. Есть ли ограничение по длине?

Определено ли поведение или реализация ANSI-C? Если более поздние, то что есть на MacOSX, Linux и Windows MSVC?


person Lothar    schedule 08.02.2010    source источник
comment
По опыту, задачи/тред с более высоким приоритетом будут размещать свой текст где-то в тексте треда с более низким приоритетом. Это можно решить, если одна задача выводится из очереди, а другая задача добавляется в очередь.   -  person Thomas Matthews    schedule 09.02.2010


Ответы (4)


Это может быть смешано.

Если у вас есть более одного потока/процесса, записывающего в один и тот же файл, вам необходимо использовать блокировку.

Альтернативой является отправка сообщений журнала в выделенную службу/поток. Отличным инструментом для внедрения является syslog, который обязательно установлен на всех unix и может работать в Windows.

person Will    schedule 08.02.2010
comment
Насколько я понимаю, в общем сценарии: общий совет заключается в том, что вы должны заблокировать файл вручную, но при конкретном сценарии OP входа в файл - нет необходимости блокировать файл. Каждая строка, которую вы отправляете в fwrite(line), НЕ будет разбита или искажена. Но последовательные вызовы fwrite() из процесса1 могут не привести к появлению последовательных строк в файле журнала (если процесс2 также параллельно записывает строки). Поэтому, если вы только добавляете строки в файл, кажется, что использование fwrite() безопасно. Если вы изменяете несколько мест в файле (например, данные и индекс), вам абсолютно необходимо использовать блокировку. - person Dimitry K; 25.12.2020
comment
Кажется, описанное мной поведение гарантируется только тогда, когда файл открыт для записи в режиме APPEND. См. stackoverflow.com/a/35258623/1168382. - person Dimitry K; 25.12.2020

Проведя небольшое исследование, я обнаружил следующее по этой ссылке:

Стандарт POSIX требует, чтобы операции C stdio FILE* были атомарными. POSIX-совместимые библиотеки C (например, в Solaris и GNU/Linux) имеют внутренний мьютекс для сериализации операций над FILE*s.

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

Таким образом, для версии 3.0 на вопрос «безопасна ли многопоточность для ввода-вывода» следует ответить «безопасна ли библиотека C вашей платформы для ввода-вывода?» Некоторые по умолчанию, некоторые нет; многие предлагают несколько реализаций библиотеки C с различными компромиссами между безопасностью потоков и эффективностью. Вы, программист, всегда должны заботиться о нескольких потоках.

Кроме того, поскольку у вас есть два разных FILE* в двух разных процессах, я думаю, у вас нет выбора.

person yeyeyerman    schedule 08.02.2010
comment
Но у каждого процесса есть свой ФАЙЛ? - person Will; 08.02.2010
comment
Также в Windows fwrite является атомарным. источник: Потому что это функция блокирует вызывающий поток, она потокобезопасна. Чтобы узнать о версии без блокировки, см. _fwrite_nolock. - person rustyx; 17.08.2016

Из «man flockfile» в Debian lenny функции stdio являются потокобезопасными.

Существуют небезопасные для потоков функции stdio, "man unlocked_stdio" для более подробной информации.

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

person cyfdecyf    schedule 16.11.2010

fwrite для Visual Studio блокирует вызывающий поток и, следовательно, является потокобезопасным.

person Lefteris E    schedule 27.11.2013