Manipulating Data Structures

The kernel provides the already_uses function to test whether module A requires another module B: kernel/module.c

static int already_uses(struct module *a, struct module *b)

10To improve readability, I have not specified the files with their full pathnames as they would appear in modules.dep. Additionally, the example is slightly simplified.

struct module_use *use;

list_for_each_entry(use, &b->modules_which_use_me, list) { if (use->module_which_uses == a) { return 1;

return 0;

If A depends on B, the modules_which_use_me list of B must contain a pointer to the module instance of A. This is why the kernel looks through the list step by step and checks the pointers in module_which_uses. If a matching entry is found — in other words, if the dependency really exists — 1 is returned; otherwise, the function terminates and returns 0 .

use_module is used to establish the relation between A and B — module A needs module B to function correctly. It is implemented as follows:

kernel/module.c

static int use_module(struct module *a, struct module *b) {

struct module_use *use;

if (!strong_try_module_get(b)) return 0;

use = kmalloc(sizeof(*use), GFP_ATOMIC); if (!use) {

printk("%s: out of memory loading\n", a->name);

module_put(b);

return 0;

use->module_which_uses = a;

list_add(&use->list, &b->modules_which_use_me); return 1;

already_uses first checks whether the relation has already been established. If so, the function can return immediately (a NULL pointer as a dependent module is also interpreted as meaning that the relation already exists). If not, the reference counter of B is incremented so that it can no longer be removed — after all, A insists on its presence. The strong_try_module_get used for this purpose is a wrapper around the aforementioned try_module_get function; it deals with the situation in which the module is in the process of being loaded:

kernel/module.c static inline int strong_try_module_get(struct module *mod) {

if (mod && mod->state == MODULE_STATE_COMING)

return 0; return try_module_get(mod);

It is not complicated to establish the relation. A new instance of module_use, whose module_which_uses pointer is set to the module instance of A, is created. The new module_use instance is added to the list list of B.

Continue reading here: Binary Structure of Modules

Was this article helpful?

0 0