Подтвердить что ты не робот

Гарантированное удаление файла после завершения программы (C/С++)

Win32 CreateFile имеет FILE_FLAG_DELETE_ON_CLOSE, но я нахожусь в Linux.

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

Я знаю об RAII. Я знаю о сигналах. Я знаю о atexit(3). Я знаю, что могу открыть файл и немедленно удалить его, и файл останется доступным до тех пор, пока дескриптор файла не будет закрыт (что даже приведет к сбою). Ни одно из них не похоже на полное и простое решение:

  • RAII: был там, сделал это: у меня есть объект, деструктор которого удаляет файл, но деструктор не вызывается, если программа завершается сигналом. Сигналы
  • : Я пишу низкоуровневую библиотеку, которая делает запись обработчика сигнала сложным предложением. Например, что, если приложение использует сигналы самостоятельно? Я не хочу наступать на все пальцы. Я мог бы подумать о некотором умном использовании sigaction(2), чтобы справиться... но пока не задумался над этой возможностью.
  • atexit(3): кажется бесполезным, поскольку он не вызывается во время аномального завершения (например, через сигнал).
  • preemptive unlink(2): это довольно хорошо, за исключением того, что мне нужно, чтобы файл оставался видимым в файловой системе (в противном случае системе сложнее отслеживать/устранять неполадки).

Что бы вы сделали здесь?

Дальнейшее объяснение

Я удалил одну деталь в своем оригинальном посте, и теперь я понял, что должен был включить. "Файл" в этом случае не является строго нормальным файлом, а скорее представляет собой очередь сообщений POSIX. Я создаю его через mq_open(). Его можно закрыть с помощью mq_close() или close() (первый - это псевдоним для последней в моей системе). Его можно удалить из системы через mq_unlink(). Все это делает его аналогичным регулярному файлу, за исключением того, что я не могу выбрать каталог, в котором находится файл. Это делает текущий самый популярный ответ (размещение файла в /tmp) неработоспособным, потому что "файл" создается системой в виртуальной файловой системе с очень ограниченной емкостью. (Я установил виртуальную файловую систему в /dev/mqueue, следуя примеру в man mq_overview).

Это также объясняет, почему мне нужно, чтобы имя оставалось видимым (что делает немедленный подход незаменимым): "файл" должен быть разделен между двумя или более процессами.

4b9b3361

Ответ 1

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

Если нет, то, вероятно, это не идеальное решение. Я хотел бы рассмотреть возможность комбинирования стратегии обработки сигналов с тем, что предлагает Камиль Кисиэль. Вы можете отслеживать обработчики сигналов, установленные перед установкой обработчиков сигналов. Если обработчик по умолчанию - SIG_IGN, вы обычно не будете устанавливать свой собственный обработчик; если это SIG_DFL, вы бы это вспомнили; если это что-то другое - пользовательский обработчик сигналов - вы бы запомнили этот указатель и установили свой собственный. Когда ваш обработчик был вызван, вы сделаете все, что вам нужно, а затем вызовите запоминающегося обработчика, таким образом, привяжите обработчики. Вы также установили обработчик atexit(). Вы также будете документировать, что вы это делаете, и сигналы, для которых вы это делаете.

Обратите внимание, что обработка сигналов - это несовершенная стратегия; SIGKILL нельзя поймать, и обработчик atexit() не будет вызван, и файл будет оставлен.

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

Ответ 2

Если вы просто создаете временный файл, просто создайте его в /tmp или в его подкаталоге. Затем приложите все усилия, чтобы удалить его, когда закончите с помощью atexit(3) или аналогичного. Пока вы используете уникальные имена, выбранные через mkstemp(3) или подобные, даже если они не могут быть удалены из-за сбоя программы, вы не рискуете прочитать его снова при последующих прогонах или других таких условиях.

В этот момент это всего лишь системная проблема сохранения /tmp clean. Большинство дистрибутивов стирают его при загрузке или завершении работы или запускают обычный cronjob для удаления старых файлов.

Ответ 3

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

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

Ответ 4

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

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

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

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

Временные имена файлов были основаны на UUID, чтобы избежать столкновений.

Ответ 5

Я только что присоединился к stackoverflow и нашел вас здесь:)

Если вам сложно управлять файлами mq и не создавать их нагромождения, вам действительно не нужно гарантировать удаление файла после его завершения. Если вы просто хотите, чтобы ненужные файлы были нагромождены, вам может понадобиться хранить журнал. Добавьте запись в файл журнала после открытия mq, другую запись, когда она закрыта, и когда ваша библиотека инициализирована, проверьте наличие несогласованности в журнале и выполните любые действия, необходимые для исправления несогласованности. Если вы беспокоитесь о сбое при вызове mq_open/mq_close, вы также можете добавить запись журнала непосредственно перед вызовом этих функций.

Ответ 6

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

Ответ 7

Вам действительно нужно, чтобы имя оставалось видимым?

Предположим, вы берете опцию немедленного открепления файла. Тогда:

  • preemptive unlink (2): это довольно хорошо, за исключением того, что мне нужно, чтобы файл оставался видимым в файловой системе (в противном случае системе сложнее отслеживать/устранять неполадки).

    Вы по-прежнему можете отлаживать удаленный файл, поскольку он все равно будет отображаться под /proc/$pid/fd/. До тех пор, пока вы знаете pids ваших процессов, перечисление их открытых файлов должно быть легким.

  • имена должны оставаться видимыми во время нормальной работы, поскольку они распределяются между программами.

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

Ответ 8

  • У вас есть справочник по хранению временных файлов в вашем dot-каталоге.
  • При создании временного файла сначала создайте файл учета в каталоге учета, содержащий путь или UUID, в ваш временный файл.
  • Создайте этот временный файл.
  • Когда temp файл удален, а затем удалите файл учета.
  • Когда программа запускается, отсканируйте каталог бухгалтерского учета для любых файлов, содержащих пути к временным файлам, и попробуйте удалить их, если они найдены, они удаляют файлы бухгалтерского учета.
  • (Лог шумит, если какой-либо шаг не работает.)

Я не вижу способов сделать это проще. Это шаблон, который должна пройти любая программа качества продукции; +500 линий легко.