2013-12-02 4 views
0

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

+0

Возможно, создается избыточный массив указателей файлов, которые вилки будут обновлять до открытия файла? – ciphermagi

+2

Вы можете в принципе удалить (отменить связь) файл немедленно. Это «удалит» файл с логической точки зрения, но физическое хранилище останется до тех пор, пока другая программа откроет его. Все, что пытается сделать другой процесс, по-прежнему будет работать. Когда другой процесс закрывает файл и выходит, от него ничего не остается. – Damon

+0

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

ответ

1

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

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», обычно это скрипт, исполняющий двоичный файл, зависящий от рабочего стола, - это может работать или не работать. –

1

Вы можете использовать либо Inotify (see man 7 inotify) или файл аренды (see 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 исследует целевой файл для выбора приложения, вы не можете предположить, что первое закрытие является окончательным закрытием; вам также нужно дождаться определенного периода, указанного выше, чтобы убедиться, что приложение-открытая цепочка завершена. Затем, если есть столько закрытий, сколько было открыто, файл может быть отсоединен. В противном случае вы будете ждать оставшихся закрытий и отключите файл после последнего.

С file leases метод немного проще, но и более ограничен. Вы можете получать только файлы в обычных файлах, принадлежащих самому пользователю. Вы можете получить аренду для чтения только в том случае, если файл не открыт для записи каким-либо процессом (включая другие дескрипторы этого же процесса). Вы можете получить аренду записи только в том случае, если файл вообще не открыт каким-либо процессом (включая другие дескрипторы файлов этим же процессом). В то время как вы держите аренду, любой другой процесс, открывающий файл (если вы держите аренду в лизинге), или пытаетесь его изменить (если вы держите на нем чтение или запись на нем), выдается сигнал SIGIO (по умолчанию вы может изменить его на сигнал в реальном времени), который должен быть отправлен владельцу аренды. Он имеет до /proc/sys/fs/lease-break-time секунд, чтобы понизить или отпустить аренду, пока ядро ​​не сломает его принудительно; в течение этого времени модификатор открытия/файла будет заблокирован по вызову 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 или файловая аренда.)

Смежные вопросы