C проверить, открыт ли файл
Обновлено: 21.11.2024
Проверить, открыт ли файл для записи (unix)
Моя программа сканирует каталог на наличие новых файлов, а затем пересылает их дальше. Однако я не могу переслать файл, пока он не будет завершен, и, насколько мне известно, единственный способ узнать, завершен ли файл, — это если к нему не обращается никакой другой процесс.
Я попытался проверить наличие блокировок записи с помощью fcntl, но либо я использую его неправильно, либо процесс не устанавливает блокировку записи для файла.
По сути, я ищу что-то похожее на fuser или lsof . Какую команду/библиотеку я ищу здесь? Не говорите "exec", потому что нет смысла брать полное колесо, когда вам нужна только спица.
Заранее спасибо,
-IsmAvatar
(Если вы хотите, чтобы я опубликовал код, который я пытался проверить на наличие замков, так и скажите, но я решил, что там больше нечего сказать)
Первоначальное сообщение от IsmAvatar2
Моя программа состоит в том, чтобы сканировать каталог на наличие новых файлов, а затем пересылать их дальше. Однако я не могу переслать файл, пока он не будет завершен, и, насколько мне известно, единственный способ узнать, завершен ли файл, — это если к нему не обращается никакой другой процесс.
Поскольку вам не нужно открывать файл при сканировании каталога, трудно сказать, что вы имеете в виду — вас беспокоят другие процессы, а не часть вашей программы, работающей в системе, которая может обращаться к файлу ?
Да. Моя программа должна сканировать каталог на наличие *новых*, *завершенных* файлов, созданных другим процессом.
Программа 1 (не под моим контролем) открывает файл "out1.txt" для записи.
P1 записывает несколько байтов в файл.
P1 закрывает файл.
P1 открывает файл "out2.txt" для записи.
P1 записывает несколько байтов в файл, но не заканчивает.
Программа 2 (моя программа) открывает каталог и находит "out1.txt"
P2 обнаруживает, что файл закрыт и завершен, поэтому передает свою информацию.
P2 затем находит "out2.txt"
P2 обнаруживает, что файл все еще открыт, поэтому игнорирует его.
P2 больше не находит файлов, закрывает каталог и завершает работу (до повторного запуска)
P1 завершает запись "out2.txt" и закрывает его.
Первоначальное сообщение от IsmAvatar2
Мне никогда не приходилось сталкиваться с этим, поэтому я не сильно помогу — моей первой мыслью было попробовать что-нибудь с fcntl(), но я вижу, что вы уже это сделали.
Большинство людей считают это задачей сценария оболочки, где вы можете использовать lsof и т. д. "по умолчанию". Я предполагаю, что вам все равно придется использовать system/exec/popen для доступа к оболочке.
Меня беспокоит, что у моей программы может не быть доступа к lsof или fuser, поскольку они часто требуют привилегий root. Я также надеялся, что смогу использовать их подпрограммы более низкого уровня без необходимости использовать всю программу и анализировать вывод. Но, конечно, просмотр исходного кода lsof может занять несколько часов.
Опубликуйте фрагмент кода, который вызывает fcntl(); P2 необходимо открыть "out2.txt" для записи в эксклюзивном режиме, и мне кажется, что вместо этого вы пытаетесь получить общую блокировку.
Здравствуйте.
Возможно, вы не видели нижнюю часть справочной страницы fuser. В разделе man 2 есть функция фьюзера. Сам я ею никогда не пользовался.
Редактировать:
Извините, в Linux нет функции фьюзера, я искал в своей системе Tru64. В Linux проверьте /proc/pid/fd список используемых файлов.
Согласно документации fcntl, если блокировка не обнаружена, она сохранит структуру прежней, но заменит режим на UNLCK, что здесь и происходит.
Златко, ты про это?
Fuser не может сообщать ни о каких процессах, для которых у него нет разрешения
просматривать таблицу файловых дескрипторов. Чаще всего эта проблема возникает
при поиске сокетов TCP или UDP при запуске fuser от имени пользователя без полномочий root. В этом случае фьюзер сообщит об отсутствии доступа
Потому что "man 2 fuser" ничего не содержит: "Нет записи для fuser в разделе 2 руководства"
Независимо от того, когда я пытаюсь запустить его без рута, я получаю следующее:
$ fuser
bash: fuser: команда не найдена
$
Первоначальное сообщение от IsmAvatar2
Златко, ты про это?
Потому что "man 2 fuser" ничего не содержит: "Нет записи для fuser в разделе 2 руководства"
Независимо от того, когда я пытаюсь запустить его без рута, я получаю следующее:
$ fuser
bash: fuser: команда не найдена
$
Да, в моем редактировании я имел в виду, что в Linux нет функции фьюзера C. Я предполагаю, что вы используете линукс. Я обнаружил, что могу посмотреть в каталоге /proc/pid/fd процесс, которым я владею, но не процесс других пользователей.Если процесс, создающий файл, принадлежит тому же пользователю, что и ожидающий его процесс, у ожидающего не должно возникнуть проблем с чтением каталога fd.
Если у вас есть доступ к исходному коду создателя, блокировка файла, такая как lockf(), вероятно, будет проще.
Запрос монопольной блокировки завершится ошибкой, если файловый дескриптор не открыт с доступом для записи.
Вместо того, чтобы пытаться получить информацию о блокировке файла, попробуйте установить на него блокировку.
Возвращаемое значение fcntl() указывает, существует ли уже блокировка для этого файла.
Златко: Я не могу редактировать источник процесса изменения этих файлов. /proc/pid/fd звучит неплохо, но как узнать, какие из них относятся к интересующему меня файлу?
itCbitC: Чтобы лучше проверить вашу идею, я создал 2 процесса.
Первый открывает файл на запись, ждет 5 секунд, а затем закрывает его и завершает работу.
Второй просто пытается установить блокировку записи в тот же файл (согласно вашему коду) и сообщает о возвращаемом значении и любых изменениях в структуре.
Я запустил первый, а за эти 5 секунд я запустил второй. Второй сообщает возвращаемое значение 0 (блокировка предоставлена) и никаких изменений в структуре (режим: 1, все остальное равно 0).
Если я не ошибаюсь, это подтверждает, что файл может быть открыт для записи без блокировки записи, что еще раз подтверждает, что мне нужен другой способ определить, открыт файл для записи или нет. цитата>
В этом руководстве рассказывается, как проверить, существует ли файл в C. Чтобы проверить, существует ли файл, попробуйте открыть файл в режиме чтения или записи. Эта программа открывает файл в режиме чтения.
Функция fopen() для проверки существования файла в C
Здесь имя файла demo.txt . Программа C и файл demo.txt находятся в одном каталоге. Таким образом, файл существует.
Если расположение программы C и расположение файла отличаются, мы должны указать полный путь к файлу.
Мы можем создать пользовательскую функцию и проверить, существует ли файл или нет. Ниже приведена программа с пользовательской функцией.
Программа напечатает, что файл существует, если файл demo.txt и программа C находятся в одном и том же месте. Если программа C и имя файла находятся в разных местах, мы должны указать полный путь к файлу.
Функция stat() для проверки существования файла в C
Мы читаем атрибуты файла с помощью функции stat() вместо чтения данных из файла. Эта функция вернет 0, если операция выполнена успешно; в противном случае он вернет -1 , если файл не существует.
Программа напечатает, что файл существует, если файл demo.txt и программа C находятся в одном и том же месте. Если программа C и имя файла находятся в разных местах, мы должны указать полный путь к файлу.
Функция access() для проверки существования файла в C
Еще один способ проверить, существует ли файл, — использовать функцию access(). Заголовочный файл unistd.h имеет доступ к функции для проверки существования файла.
Мы можем использовать R_OK для разрешения на чтение, W_OK для разрешения на запись и X_OK для разрешения на выполнение. Мы можем использовать их вместе как R_OK|W_OK для разрешения на чтение и запись.
Здесь C:\TEMPdemo.txt — это расположение файла. Если файл существует, он печатает файл найден; в противном случае он печатает файл не найден. Расположение программы и файла demo.txt совпадает. В противном случае мы должны указать местоположение файла. Комбинация функций stat() и access() — хороший выбор для операционной системы Linux.
Другой способ использования функции access() показан ниже:
Статьи DelftStack написаны такими же фанатами программного обеспечения, как и вы. Если вы также хотите внести свой вклад в DelftStack, написав платные статьи, вы можете посетить страницу «Написать для нас».
Статья по теме — файл C
сообщить об этом объявлении
Читайте также: