2009-11-16 4 views
16

Je lisais le LKMPG (See Section 4.1.4. Unregistering A Device) et je ne savais pas quand utiliser les fonctions try_module_get/module_put. Certains exemples de LKMPG les utilisent, d'autres non. Pour ajouter à la confusion, try_module_get apparaît 282 fois dans 193 fichiers dans la source 2.6.24, mais dans Linux Device Drivers (LDD3) et Essential Linux Device Drivers, ils n'apparaissent même pas dans un seul exemple de code.Linux Kernel Modules: Quand utiliser try_module_get/module_put

Je pensais que peut-être qu'ils étaient liés à l'ancienne interface register_chrdev (remplacée en 2.6 par l'interface cdev), mais ils apparaissent seulement ensemble dans les mêmes fichiers 8 fois:

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

Alors, quand est-il approprié utiliser ces fonctions et sont-elles liées à l'utilisation d'une interface particulière ou d'un ensemble de circonstances?

Modifier

I chargé le sched.c exemple de la LKMPG et essayé l'expérience suivante:

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

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

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

Cela me conduit à croire que le noyau maintenant-t-il sa propre comptabilité et obtient/puts peut être obsolète. Quelqu'un peut-il vérifier cela?

+0

il y a une occurrence de 'try_module_get' au chapitre 14, dans la sous-section' manipulation' de comptage de référence (page 367) –

+0

Je voulais dire le livre LDD dans mon commentaire précédent –

Répondre

15

Vous ne devriez pratiquement jamais utiliser try_module_get (THIS_MODULE); à peu près toutes ces utilisations sont dangereuses car si vous êtes déjà dans votre module, il est trop tard pour augmenter le nombre de références - il y aura toujours une (petite) fenêtre où vous exécutez du code dans votre module mais sans incrémenter la référence compter. Si quelqu'un supprime le module exactement dans cette fenêtre, alors vous êtes dans la mauvaise situation de l'exécution du code dans un module non chargé.

L'exemple particulier que vous avez lié à LKMPG où le code ne méthode try_module_get() à l'air libre() serait traitée dans le noyau moderne en définissant le champ .owner dans file_operations struct:

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

cette volonté faire le code VFS prendre une référence au module avant appelant, ce qui élimine la fenêtre dangereuse - soit le try_module_get() réussira avant l'appel à .open(), ou le try_module_get() échouera et le VFS n'appelle jamais dans le module. Dans les deux cas, nous n'exécutons jamais de code à partir d'un module qui a déjà été déchargé.

Le seul bon moment pour utiliser try_module_get() est lorsque vous voulez prendre une référence sur un module différent avant d'appeler dans ou de l'utiliser d'une certaine façon (par exemple que le fichier code ouvert fait dans l'exemple je l'ai expliqué au dessus). Il y a un certain nombre d'utilisations de try_module_get (THIS_MODULE) dans la source du noyau mais la plupart d'entre elles sont des bugs latents qui doivent être nettoyés.

La raison pour laquelle vous n'étiez pas en mesure de décharger l'exemple sched est que votre commande

$ tail /proc/sched -f & 

conserve/proc/sched ouvert, et à cause de

 Our_Proc_File->owner = THIS_MODULE; 

dans le code sched.c, L'ouverture/proc/sched incrémente le nombre de références du module sched, ce qui représente la référence que votre lsmod affiche.D'un bref survol du reste du code, je pense que si vous relâchiez/proc/sched en supprimant votre commande tail, vous seriez en mesure de supprimer le module sched.

+0

--- Eh bien, comme je sais récemment en travaillant Sur le pilote de périphérique de surveillance, il existe une fonctionnalité appelée «no-out-out», ce qui signifie qu'une fois ce périphérique démarré, vous ne pouvez pas l'arrêter. Pour cette raison, ce module n'a pas pu être déchargé, ainsi, dans l'implémentation open() du pilote de périphérique, un __module_get (THIS_MODULE) est utilisé, avec le module pilote de périphérique, lorsque le nombre de références d'un module n'est pas nul , vous ne pouvez pas le décharger. En conclusion, c'est peut-être le cas où vous devez utiliser module_get, module_put, etc. Merci. –

+0

Un 'try_module_get' de la fonction' init_module' est sûr, mais un module_put correspondant devrait être fait plus tôt que 'cleanup_module'. – fche

Questions connexes