file_operations Вопрос, как мне узнать, если процесс, открывший файл для записи, решил закрыть его? - PullRequest
0 голосов
/ 11 мая 2010

В настоящее время я пишу простой «многоадресный» модуль.

Только один процесс может открыть файл файловой системы proc для записи, а остальные могут открыть его для чтения. Для этого я использую обратный вызов inode_operation .permission, проверяю операцию и, когда обнаруживаю, что кто-то открывает файл для записи, я устанавливаю флаг ON.

Мне нужен способ определить, решил ли процесс, открывший файл для записи, закрыть файл, чтобы я мог установить флаг OFF, чтобы кто-то еще мог открыть для записи.

В настоящее время, если кто-то открыт для записи, я сохраняю current-> pid этого процесса, и когда вызывается обратный вызов .close, я проверяю, является ли этот процесс тем, который я сохранил ранее.

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

Спасибо!

Ответы [ 2 ]

2 голосов
/ 12 мая 2010

Нет, это не безопасно. Рассмотрим несколько сценариев:

  • Процесс A открывает файл для записи, а затем fork() s, создавая процесс B. Теперь и A, и B имеют файл, открытый для записи. Когда процесс A закрывает его, вы устанавливаете флаг в 0, но процесс B все еще имеет его открытым для записи.

  • Процесс A состоит из нескольких потоков. Поток X открывает файл для записи, но поток Y закрывает его. Теперь флаг установлен на 1. (Помните, что ->pid в пространстве ядра на самом деле является пользовательским пространством thread ID).

Вместо того, чтобы делать что-то на уровне инода, вы должны делать это в .open и .release методах вашей file_operations структуры.

Личные данные вашего inode должны содержать struct file *current_writer;, инициализированный до NULL. В методе file_operations.open, если он открывается для записи, проверьте current_writer; если он равен NULL, установите для открываемого struct file *, в противном случае откройте с ошибкой EPERM. В методе file_operations.release убедитесь, что высвобождаемый struct file * равен индексу current_writer - если да, установите current_writer обратно в NULL.

PS: Бандан также прав, что вам нужна блокировка, но для защиты current_writer.

должно быть достаточно использования существующего i_mutex инода.
0 голосов
/ 11 мая 2010

Надеюсь, я правильно понял ваш вопрос: когда кто-то хочет записать в ваш файл proc, вы устанавливаете переменную с именем flag в 1, а также сохраняете current-> pid в глобальной переменной. Затем, когда вызывается любая точка входа close (), вы проверяете current-> pid экземпляра close () и сравниваете его с сохраненным значением. Если это соответствует, вы выключаете флаг. Правильно ?

Рассмотрим следующую ситуацию: процесс A хочет выполнить запись в ваш ресурс proc, и поэтому вы проверяете обратный вызов разрешения. Вы видите, что флаг равен 0, поэтому вы можете установить его на 1 для процесса А. Но в этот момент планировщик обнаруживает, что процесс А израсходовал свою долю времени, и выбирает другой процесс для запуска (флаг по-прежнему равен o!). Через некоторое время появляется процесс B, желающий также записать в ваш ресурс proc, проверяет, что флаг равен 0, устанавливает его в 1, а затем приступает к записи в файл. К сожалению, в данный момент процесс А запланирован для повторного запуска, и, поскольку он считает, что флаг равен 0 (запомните, до того, как планировщик его опередил, флаг был равен 0), он устанавливает его в 1 и выполняет запись в файл. Конечный результат: данные в вашем ресурсе proc повреждены.

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

...