Ответ 1
Вам по существу никогда не придется использовать try_module_get (THIS_MODULE); почти все такие виды использования являются небезопасными, поскольку, если вы уже находитесь в своем модуле, слишком поздно, чтобы уменьшить количество ссылок - всегда будет (небольшое) окно, в котором вы выполняете код в своем модуле, но не увеличиваете ссылку сосчитать. Если кто-то удаляет модуль именно в этом окне, значит, вы находитесь в плохой ситуации с запуском кода в незагруженном модуле.
Конкретный пример, который вы связали в LKMPG, где код try_module_get() в методе open() будет обрабатываться в современном ядре, установив поле .owner в struct file_operations:
struct file_operations fops = {
.owner = THIS_MODULE,
.open = device_open,
//...
};
это приведет к тому, что код VFS возьмет ссылку на модуль перед вызовом в него, что устраняет небезопасное окно - либо try_module_get() будет успешным до вызова метода .open(), либо try_module_get() не удастся и VFS никогда не будет звонить в модуль. В любом случае мы никогда не запускаем код из модуля, который уже был выгружен.
Единственное удобное время для использования try_module_get() - это когда вы хотите взять ссылку на другой модуль перед тем, как называть его или использовать его каким-либо образом (например, как это делает код открытия файла в примере, описанном выше). Существует несколько применений try_module_get (THIS_MODULE) в источнике ядра, но большинство, если не все, являются скрытыми ошибками, которые следует очистить.
Причина, по которой вы не смогли выгрузить пример расписания, заключается в том, что ваш
$ tail /proc/sched -f &
команда сохраняет /proc/sched open и из-за
Our_Proc_File->owner = THIS_MODULE;
в коде sched.c, открытие /proc/sched увеличивает счетчик ссылок модуля расписания, который учитывает 1 ссылку, которую показывает ваш lsmod. Из краткого описания остальной части кода я думаю, что если вы отпустите /proc/sched, убив команду tail, вы сможете удалить модуль расписания.