Является ли реализация fprintf() в glibc поточно-ориентированной?

Является ли fprintf поточно-ориентированным? Руководство glibc, похоже, говорит, что это так, но мое приложение, которое записывает в файл с помощью одного вызова fprintf(), похоже, смешивает частичные записи из разных процессов.

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

Глядя на файл, некоторые записи перемешаны.

edit 2: Кажется, проблема, которую я вижу, может быть связана с тем, что "рабочие потоки" lighttpd на самом деле являются отдельными процессами: http://redmine.lighttpd.net/wiki/lighttpd/Docs:MultiProcessor

Проблемы

Запустив 2 или более процессов в одном сокете, вы получите лучший параллелизм, но у вас будет несколько недостатков, о которых вы должны знать:

  • mod_accesslog может создать поврежденные журналы доступа, так как один и тот же файл открывается дважды и НЕ синхронизируется.
  • mod_status будет иметь n отдельных счетчиков, по одному для каждого процесса.
  • mod_rrdtool завершится с ошибкой, поскольку он получает одну и ту же метку времени дважды.
  • mod_uploadprogress не будет показывать правильный статус.

3 ответа

Решение

Вы путаете две концепции - запись из нескольких потоков и запись из нескольких процессов.

Внутри процесса можно гарантировать, что один вызов fprintf завершен до того, как следующему будет разрешен доступ к выходному буферу, но как только ваше приложение накачает этот вывод в файл, вы окажетесь во власти ОС. Без какого-либо механизма блокировки на основе ОС вы не сможете гарантировать, что совершенно другое приложение не запишет в ваш файл журнала.

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

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

Текущий стандарт C++ не говорит ничего полезного о параллелизме, равно как и стандарт C 1990 года. (Я не читал стандарт C 1999 года, поэтому не могу его комментировать; будущий стандарт C++0x говорит о многом, но я не знаю точно, что это за руки.)

Это означает, что сам fprintf(), вероятно, не является ни потокобезопасным, ни каким-либо иным образом, и что это будет зависеть от реализации. Я прочитал в точности то, что говорится в документации glibc, и сравнил это с тем, что вы делаете.

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