C проверить, открыт ли файл

Обновлено: 01.07.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


сообщить об этом объявлении

Читайте также: