Linux |
CentOS 4.8 |
|
modules(2) |
get_kernel_syms, create_module, init_module, delete_module − Support des modules chargeables de Linux. |
#include <linux/module.h> int get_kernel_syms(struct kernel_sym *table); int create_module(char *module_name, unsigned long size); int init_module(char *module_name, char *code,
unsigned codesize, int delete_module(char *module_name); struct kernel_sym { |
unsigned long value; |
||
char name[SYM_MAX_NAME]; |
}; struct mod_routines { |
int (*init)(void); |
|
void (*cleanup)(void); |
}; struct module_ref { |
struct module *module; |
|
struct module_ref *next; |
}; struct internal_symbol { |
void *addr; |
|
char *name; |
}; struct symbol_table { |
int size; /* total, including string table!!! */ |
|
int n_symbols; |
|
int n_refs; |
|
struct internal_symbol symbol[0]; |
|
struct module_ref ref[0]; |
}; |
Ces appels systèmes ne sont pas encore inclus dans les bibliothèques (au 14 Mai 95) ce qui signifie qu’ils doivent être appelés avec le mécanisme syscall(__NR_function). get_kernel_syms(table) propose deux services : premièrement, si table est NULL, cet appel retournera simplement le nombre de symboles disponibles, y compris les noms des modules. Cette valeur peut servir à allouer de la mémoire pour autant d’éléments du type struct kernel_sym. Si table n’est pas NULL, cet appel va copier tous les symboles du noyau et les noms de modules (avec les numéros de version) dans la zone mémoire pointée par table. Les données sont triées dans l’ordre LIFO d’insertion des modules. Chaque module est décrit par une entrée dans cette table, suivi par les entrées décrivant les symboles exportés par le module. Remarquez que pour les symboles, la partie value
de la structure contiendra l’adresse au sein du
noyau de la structure décrivant le
module. A la fin des symboles résidents du noyau, apparaîtra un symbole dont le nom sera #. Cette information peut servir à construire une table de référence des modules où ils seront empilés. create_module(module_name, size) allouera size octets dans l’espace du noyau pour un module, et créera également les structures internes au noyau pour le nouveau module nommé name. Ce module existera dès lors dans l’espace du noyau avec un statut MOD_UNINITIALIZED. init_module(module_name, code, codesize, routines, symtab) est le véritable chargeur (loader) de module, qui va insérer le module nommé name au sein du noyau. Les paramètres code et codesize correspondent au code objet binaire du module, qui fait codesize octets de long. Si l’on effectue un OU binaire entre le paramètre codesize et MOD_AUTOCLEAN, le module sera soumis au nettoyage automatique, c’est à dire l’élimination périodique des modules inutilisés. Les 4 premiers octets de l’image du module seront utilisés comme compteur de référence par le noyau, mis à jour par les macros MOD_INC_USE_COUNT et MOD_DEC_USE_COUNT. Ce compteur contiendra également le bit MOD_AUTOCLEAN et un bit MOD_VISITED qui sont utilisés pour le nettoyage automatique. Les fonctions décrites dans routines
serviront à démarrer et
arrêter le module. Ces pointeurs devraient
contenir l’adresse des fonctions init_module()
et cleanup_module() définies pour tous
les modules chargeables. Spécificités : Les éléments n_symbols et n_refs indiquent combien de symboles et combien de références aux autres modules sont inclus dans la structure symbol_table. Immédiatement après ces entiers se trouve la table des symboles. L’élément name dans chaque struct internal_symbol ne doit pas être un pointeur classique, mais l’ offset de la chaîne correspondante dans la table, relativement au début de la structure symbol_table. Après la liste de tous les symboles définis, la structure symbol_table continue avec une table des références de modules, décrites par les éléments struct module_ref. Seul le champ module de ces structures doit être initialisé. Les adresses de modules obtenues précédemment avec get_kernel_syms pour les éléments dont le nom commence par # doivent être copiées dans ces champs. Si le module peut être correctement chargé, et si l’appel de la fonction init_module() réussit également, le statut du module deviendra MOD_RUNNING. Autrement, la mémoire du noyau occupée par le module sera libérée. delete_module(module_name) doit être utilisé pour décharger un module. Si le compteur de références montre que le module n’est plus actif, et qu’aucun autre modules n’y fait référence, sa fonction cleanup_module() sera appelée. Si toutes ces étapes réussissent, la mémoire du noyau occupée par le module et ses structures sera libérée. Remarquez que si l’argument de delete_module vaut NULL, le noyau supprimera tous les modules. |
S’il se produit une erreur, toutes ces fonctions renverront −1, et la variable globale errno contiendra le code d’erreur. Un message d’erreur sera également affiché sur la console. |
Ces appels systèmes sont spécifiques à Linux, et ne doivent pas être employés dans des programmes destinés à être portables. Le support de module a été conçu par Anonymous (si je me souviens bien). |
insmod(1), rmmod(1), lsmod(1), ksyms(1), genksyms(8) |
Naan... |
Christophe Blaess, 1997. |
modules(2) |