2009-11-16 5 views
16

Ich las die LKMPG (See Section 4.1.4. Unregistering A Device) und es war mir nicht klar, wann die try_module_get/module_put Funktionen zu verwenden. Einige der LKMPG-Beispiele verwenden sie, andere nicht.Linux Kernel Modules: Wann ich try_module_get/module_put verwenden sollte

zur Verwirrung hinzuzufügen try_module_get erscheinen 282 mal in 193 Dateien in der 2.6.24 Quelle, noch in Linux Device Drivers (LDD3) und Essential Linux Device Drivers, sie erscheint in nicht einmal ein einzigen Codeb..

Ich dachte, vielleicht sie an die alte register_chrdev Schnittstelle gebunden wurden (ersetzte in 2.6 durch die cdev Schnittstelle), aber sie nur in den gleichen Dateien 8mal erscheinen zusammen:

find -type f -name *.c | xargs grep -l try_module_get | sort -u | xargs grep -l register_chrdev | sort -u | grep -c . 

Wenn also ist es angebracht, Verwenden Sie diese Funktionen und sind sie an die Verwendung einer bestimmten Schnittstelle oder einer Reihe von Umständen gebunden?

bearbeiten

ich lud die sched.c zB aus dem LKMPG und versucht, das folgende Experiment:

[email protected]:~/kernel-source/lkmpg/2.6.24$ tail /proc/sched -f & 
Timer called 5041 times so far 
[1] 14594 

[email protected]on:~$ lsmod | grep sched 
sched     2868 1 

[email protected]:~$ sudo rmmod sched 
ERROR: Module sched is in use 

Das führt mich, dass der Kernel zu glauben, jetzt ist es eigene Buchhaltung ist und die bekommt/puts kann veraltet sein. Kann das jemand verifizieren?

+0

gibt es ein Vorkommen von 'try_module_get' in Kapitel 14, im Abschnitt' Referenzzähler manipulation' (Seite 367) –

+0

bedeuten, dass ich das LDD Buch in meinem vorherigen Kommentar –

Antwort

15

Sie sollten im Wesentlichen nie try_module_get (THIS_MODULE) verwenden; ziemlich viele solcher Anwendungen sind unsicher, da es zu spät ist, die Referenzzahl zu erhöhen - wenn Sie bereits in Ihrem Modul sind - es wird immer ein (kleines) Fenster geben, in dem Sie Code in Ihrem Modul ausführen, aber die Referenz nicht erhöht haben Anzahl. Wenn jemand das Modul genau in diesem Fenster entfernt, sind Sie in der schlechten Situation, Code in einem entladenen Modul auszuführen.

Das spezielle Beispiel, das Sie in LKMPG verbunden, wo der Code() in der Methode open() in dem modernen Kernel behandelt würde nicht try_module_get durch das .owner Feld in struct file_operations Einstellung:

struct file_operations fops = { 
     .owner = THIS_MODULE, 
     .open = device_open, 
     //... 
}; 

dieser Willen Machen Sie den VFS-Code nehmen Sie einen Verweis auf das Modul vor Aufruf in, die das unsichere Fenster beseitigt - entweder die try_module_get() wird vor dem Aufruf von .open() erfolgreich sein, oder die try_module_get() wird fehlschlagen und die VFS wird nie in das Modul anrufen. In beiden Fällen führen wir niemals Code aus einem Modul aus, das bereits entladen wurde.

Die einzige gute Zeit zu nutzen try_module_get(), wenn Sie einen Verweis auf ein verschiedenen Modul nehmen wollen, bevor er in sie anrufen oder sie in irgendeiner Weise (zB als der offene Code-Datei wird in dem Beispiel, das ich erklärt über). Es gibt eine Reihe von Verwendungen von try_module_get (THIS_MODULE) in der Kernelquelle, aber die meisten, wenn nicht alle, sind latente Fehler, die bereinigt werden sollten.

Der Grund waren Sie nicht in der Lage das Sched Beispiel zu entladen ist, dass Ihr

$ tail /proc/sched -f & 

Befehl/hält proc/Sched offen, und wegen

 Our_Proc_File->owner = THIS_MODULE; 

im sched.c Code, opening/proc/sched erhöht den Referenzzähler des sched-Moduls, der die 1 Referenz berücksichtigt, die Ihr lsmod anzeigt.Von einem schnellen Überfliegen des Rests des Codes denke ich, wenn du/proc/schedest, indem du deinen Schwanzbefehl beendest, könntest du das sched Modul entfernen.

+0

--- Nun, wie ich vor kurzem wissen, während der Arbeit Beim Watchdog-Gerätetreiber gibt es eine Funktion namens "No-Way-Out", die bedeutet, dass das Gerät nach dem Start nicht mehr gestoppt werden kann. Aus diesem Grund konnte dieses Modul nicht entladen werden. Daher wird in der open() - Implementierung des Gerätetreibers ein __module_get (THIS_MODULE) verwendet, wobei das Gerätetreibermodul bekannt ist, wenn der Referenzzähler eines Moduls nicht Null ist , Sie können es nicht entladen. In einer Schlussfolgerung, vielleicht ist dies der Fall, wo Sie module_get, module_put, etc. Danke verwenden müssen. –

+0

Ein 'try_module_get' aus der 'init_module'-Funktion ist sicher, aber ein passender' module_put' müsste zu einem früheren Zeitpunkt als 'cleanup_module' erfolgen. – fche