Автор Гілка: Багатопроцесний запис у файл  (Прочитано 733 раз)

Миха́йло Даниленко

  • Гість
При написанні скрипта зіткнувся з цікавим випадком, вирішив поділитися.

Власне, є скрипт, що виконує деяку роботу зі списком задач. Задачі абсолютно незалежні одна від одної, тобто їх можна розпараллелити, що я й вирішив зробити, бо їх багато і робота в один процес займе кілька діб. Спочатку я спробував робити це через потоки, але виявилося, що ліби для виконання роботи десь щось глобально реєструють (зараз розбираюся, що саме), тож об'єкти не звільняються, і через деякий час скрипт падає, з'ївши всю пам'ять на віртуалці. Оскільки виграш від використання потоків у порівнянні з процесами в даному випадку невеликий (сама робота займає значно більше часу, ніж може зекономити відсутність копіювання даних), я вирішив робити кожного разу fork замість цього, таким чином пам'ять буде гарантовано звільнятися. Результати роботи скрипта пишуться у xml-файл — він відкривається у режимі write-only, туди пишеться заголовок, після чого кожен процес по виконанню завдання записує туди шматок тексту (доступ до файлу регулюється через mutex).

Але після відпрацювання скрипта я з подивом виявив, що заголовок xml з'явився не лише на початку файла, а й перед кожним записом, що робили підпроцеси. Власне, питання для цікавих — чому так?

ВідповідьПроблема в тому, що файл відкритий звичайним чином, з буферизацією, а заголовок недостатньо великий для того, щоб спрацював flush(). fork() створює повну копію процеса, разом з буфером запису, після чого пише свій шмат коду, що призводить до flush(), який записує і буферизований заголовок, і дані. Але лише у підпроцесі, у основному процесі буфер залишається повним, тому при наступному fork() відбувається те ж саме.