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

0

У меня есть данные, хранящиеся в памяти, которые я хочу открыть. Я создаю временный файл и fork xdg-open на ubuntu, чтобы открыть файл, используя стандартное приложение. Я хочу удалить временный файл после закрытия программы. Проблема в том, что сам xdg-open открывает другой процесс и немедленно завершает работу. Следовательно, я не знаю, какой процесс открыл файл. Я попытался получить эксклюзивную блокировку с помощью flock а также попытался unlink файл после того, как я подождал 20 srcs (чтобы убедиться, что другой процесс сначала открывает файл), вызовы преуспевают, а открытая программа просто закрывает файл. Я хочу подождать, пока программа не будет закрыта, а затем удалите файл. Кто-нибудь знает, как это сделать?

  • 0
    Может быть, создать избыточный массив файловых указателей, которые вилки будут обновлять каждый раз, когда открывают файл?
  • 2
    В принципе, вы можете немедленно удалить (отменить связь) файл. Это «удалит» файл с логической точки зрения, но физическое хранилище остается, пока другая программа его открыла. Все, что пытается сделать другой процесс, все равно будет работать. Когда другой процесс закрывает файл и завершает работу, от него ничего не остается.
Показать ещё 13 комментариев
Теги:

2 ответа

1

Вы можете использовать либо inotify (см. man 7 inotify), либо файловую аренду (см. man 2 fcntl, Leases section), чтобы обнаружить, когда другие процессы открывают и закрывают файл (с помощью inotify), или определяют, открыт ли файл другими процессами (файл сдает в аренду).

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

Это означает, что момент времени, когда system() возвращает, в основном не имеет значения. Целевой файл может быть или не быть открыт потенциальным приложением в этой точке; мы просто не знаем и не знаем этого.

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

На практике это означало бы замену system() вашей собственной реализацией с использованием fork(), setsid(), exec*() и waitpid() и waitid(); последний в цикле с коротким сном для обнаружения, когда в группе процессов больше нет процессов.

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

С помощью функции inotify() вы должны назначить часы перед выполнением команды xdg-open, а затем следить за тем, как открывается и закрывается. Поскольку возможно, что xdg-open проверяет целевой файл на выбор приложения, вы не можете предположить, что первое закрытие является окончательным закрытием; вам также нужно дождаться определенного периода, указанного выше, чтобы убедиться, что приложение-открытая цепочка завершена. Затем, если столько закрытий, сколько было открыто, файл может быть отсоединен. В противном случае вы будете ждать оставшихся закрытий и отключите файл после последнего.

При аренде файлов метод немного проще, но также более ограничен. Вы можете получать только файлы в обычных файлах, принадлежащих самому пользователю. Вы можете получить аренду для чтения только в том случае, если файл не открыт для записи каким-либо процессом (включая другие дескрипторы этого же процесса). Вы можете получить аренду записи только в том случае, если файл вообще не открыт каким-либо процессом (включая другие дескрипторы файлов этим же процессом). В то время как вы держите аренду, любой другой процесс, открывающий файл (если вы держите аренду в лизинге) или пытаетесь его изменить (если вы держите на нем чтение или запись на нем), вызовет сигнал SIGIO (по умолчанию, вы может изменить его на сигнал в реальном времени), который должен быть отправлен владельцу аренды. Он имеет до /proc/sys/fs/lease-break-time секунд, чтобы понизить или отпустить аренду, пока ядро не сломает его принудительно; в течение этого времени модификатор openener/file будет заблокирован при вызове open()/truncate().

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

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

Наконец, если использование ресурсов вызывает беспокойство, я рекомендую написать отдельный вспомогательный двоичный файл, чтобы управлять этим для вас. В основном, вместо запуска xdg-open [OPTIONS] FILENAME, вы запускаете /usr/lib/myapp/open DELAY INTERVAL [OPTIONS] FILENAME. /usr/lib/myapp/open двоичные вилки и немедленно выходят. Детский процесс выполняет xdg-open и реализует описанную выше процедуру, чтобы дождаться, пока файл не будет отсоединен. Каждый из двоичных файлов /usr/lib/myapp/open требует очень мало данных (минимальный размер резидентного набора) и ресурсов (они в основном спят), поэтому даже имея несколько десятков из них в памяти, не будет сильно стекать даже на встроенная машина Linux.

Если есть интерес, я мог бы добавить пример реализации C /usr/lib/myapp/open здесь. (Просто дайте мне знать, какой из трех подходов наиболее интересен - мониторинг группы процессов, inotify или файл).

1

Когда xdg-open не полагается на суффикс, вы можете использовать

fd = open(filename, O_RDONLY|O_CLOEXEC);
unlink(filename);

system("xdg-open /proc/%u/fd/%u", getpid(), fd); /* pseudo-code! system is not printf() like! */

close(fd);
  • 0
    Если xdg-open (или двоичный файл, который он вызывает для открытия файла) разветвляется для выполнения фактического приложения в дочернем процессе и завершает сам, вызов system() может вернуться, и дескриптор закрывается (и, следовательно, исчезает) перед фактическим Приложение может попробовать открыть его. В зависимости от того, как реализован xdg-open - обычно это скрипт, который выполняет двоичный файл, зависящий от среды рабочего стола, - это может работать или не работать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню