分类: LINUX
2016-08-17 14:43:20
linux/module.h
enum module_state {
MODULE_STATE_LIVE, //模块当前正常使用中(存活状态) 0
MODULE_STATE_COMING, //模块当前正在被加载 1
MODULE_STATE_GOING, //模块当前正在被卸载 2
};
struct module
{
enum
module_state state;//模块状态
/* Member of list of
modules */
struct list_head list;
//list是作为一个列表的成员,所有的内核模块都被维护在一个全局链表中,链表头是一个全局变量struct
//
module *modules。任何一个新创建的模块,都会被加入到这个链表的头部
模块加载由内核的系统调用init_module完成。
linux3.5.2/kernel/module.c:3009
/* This is where the real work happens */
SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs)
{
struct module *mod;
int ret = 0;
……
/* Do all the hard work */
mod = load_module(umod, len, uargs);//模块加载
……
/* Start the module */
if (mod->init != NULL)
ret = do_one_initcall(mod->init);//模块init函数调用
……
return 0;
}
系统调用init_module由SYSCALL_DEFINE3(init_module...)实现,其中有两个关键的函数调用。load_module用于模块加载,do_one_initcall用于回调模块的init函数。
/* This is
where the real work happens */
SYSCALL_DEFINE3(init_module, void __user *,
umod,
unsigned long, len, const char __user *, uargs)
{
struct module
*mod;
int ret = 0;
/* Must have permission */
if
(!capable(CAP_SYS_MODULE))
return -EPERM;
/* Only one module
load at a time, please */
if (mutex_lock_interruptible(&module_mutex)
!= 0)
return -EINTR;
/* Do all the hard work */
mod
= load_module(umod, len, uargs);
if (IS_ERR(mod)) {
mutex_unlock(&module_mutex);
return PTR_ERR(mod);
}
/* Drop lock so they can recurse */
mutex_unlock(&module_mutex);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_COMING, mod);
/* Start the module */
if
(mod->init != NULL)
ret =
do_one_initcall(mod->init);//do_initcalls里也调用了 do_one_initcall
//此处是没编译进内核时的模块加载?do_initcalls里也调用了 do_one_initcall是编译进内核的模块自动加载?
if (ret < 0)
{
/* Init routine failed: abort. Try to protect us
from
buggy refcounters. */
mod->state =
MODULE_STATE_GOING;
synchronize_sched();
module_put(mod);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod);
mutex_lock(&module_mutex);
free_module(mod);
mutex_unlock(&module_mutex);
wake_up(&module_wq);
return ret;
}
if (ret > 0) {
printk(KERN_WARNING
"%s: '%s'->init suspiciously returned %d, "
"it should
follow 0/-E convention\n"
KERN_WARNING "%s: loading module
anyway...\n",
__func__, mod->name, ret,
__func__);
dump_stack();
}
/* Now it's a first
class citizen! Wake up anyone waiting for it. */
mod->state =
MODULE_STATE_LIVE;
wake_up(&module_wq);
mutex_lock(&module_mutex);
/* Drop initial reference. */
module_put(mod);
unwind_remove_table(mod->unwind_info, 1);
module_free(mod, mod->module_init);
mod->module_init = NULL;
mod->init_size = 0;
mod->init_text_size = 0;
mutex_unlock(&module_mutex);
return 0;
}
//////////////////////////////////////////////////
模块卸载由内核的系统调用delete_module完成。
SYSCALL_DEFINE2(delete_module, const char __user *,
name_user,
unsigned int, flags)
{
struct module
*mod;
char name[MODULE_NAME_LEN];
int ret, forced = 0;
if (!capable(CAP_SYS_MODULE))
return -EPERM;
if
(strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
return
-EFAULT;
name[MODULE_NAME_LEN-1] = '\0';
if
(mutex_lock_interruptible(&module_mutex) != 0)
return
-EINTR;
mod = find_module(name);
if (!mod) {
ret =
-ENOENT;
goto out;
}
if
(!list_empty(&mod->modules_which_use_me)) {
/* Other modules
depend on us: get rid of them first. */
ret = -EWOULDBLOCK;
goto out;
}
/* Doing init or already dying? */
if
(mod->state != MODULE_STATE_LIVE) {
/* FIXME: if (force), slam
module count and wake up
waiter --RR */
DEBUGP("%s already dying\n", mod->name);
ret = -EBUSY;
goto out;
}
/* If it has an init func, it must have an exit
func to unload */
if (mod->init && !mod->exit) {
forced = try_force_unload(flags);
if (!forced) {
/*
This module can't be removed */
ret = -EBUSY;
goto
out;
}
}
/* Set this up before setting
mod->state */
mod->waiter = current;
/* Stop the machine
so refcounts can't move and disable module. */
ret = try_stop_module(mod,
flags, &forced);
if (ret != 0)
goto out;
/*
Never wait if forced. */
if (!forced && module_refcount(mod) !=
0)
wait_for_zero_refcount(mod);
mutex_unlock(&module_mutex);
/* Final destruction now noone is using
it. */
if (mod->exit != NULL)
mod->exit();//调用exit module
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod);
mutex_lock(&module_mutex);
/* Store
the name of the last unloaded module for diagnostic purposes */
strlcpy(last_unloaded_module, mod->name,
sizeof(last_unloaded_module));
unregister_dynamic_debug_module(mod->name);
free_module(mod);//卸载模块
out:
mutex_unlock(&module_mutex);
return ret;
}
函数在内核中的位置:linux-2.6.30/kernel/module.c
该函数的功能是将一个特定模块module的引用计数减1
,这样当一个模块的引用计数因为不为0而不能从内核中卸载时,可以调用此函数一次或多次,实现对模块计数的清零,从而实现模块卸载。
void
module_put(struct module *module)
{
if (module) {
unsigned int cpu =
get_cpu();
local_dec(&module->ref[cpu].count);
/* Maybe they're
waiting for us to drop reference? */
if
(unlikely(!module_is_live(module)))
wake_up_process(module->waiter);
put_cpu();
}
}
//////////////////////////////////////
/*
modprobe_path
is set via /proc/sys.
*/
char modprobe_path[KMOD_PATH_LEN] =
"/sbin/modprobe";
/**
* request_module - try to load a kernel module
* @fmt:
printf style format string for the name of the module
* @varargs: arguements
as specified in the format string
*
* Load a module using the user mode module loader. The function returns
* zero
on success or a negative errno code on failure. Note that a
*
successful module load does not mean the module did not then unload
* and
exit on an error of its own. Callers must check that the service
* they
requested is now available not blindly invoke it.
*
* If module
auto-loading support is disabled then this function
* becomes a
no-operation.
*/
kernel/kmod.c
int
request_module(const char *fmt, ...)
{
va_list args;
char
module_name[MODULE_NAME_LEN];
unsigned int max_modprobes;
int
ret;
char *argv[] = { modprobe_path, "-q", "--", module_name, NULL
};
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL
};
static atomic_t kmod_concurrent = ATOMIC_INIT(0);
#define
MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int
kmod_loop_msg;
va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN,
fmt, args);
va_end(args);
if (ret >= MODULE_NAME_LEN)
return
-ENAMETOOLONG;
/* If modprobe needs a service that is in a module, we get a
recursive
* loop. Limit the number of running kmod threads to
max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A
cleaner method
* would be to run the parents of this process, counting how
many times
* kmod was invoked. That would mean accessing the internals of
the
* process tables to get the command line, proc_pid_cmdline is
static
* and it is not worth changing the proc code just to handle this
case.
* KAO.
*
* "trace the ppid" is simple, but will fail if
someone's
* parent exits. I think this is as good as it gets. --RR
*/
max_modprobes = min(max_threads/2,
MAX_KMOD_CONCURRENT);
atomic_inc(&kmod_concurrent);
if
(atomic_read(&kmod_concurrent) > max_modprobes) {
/* We may be
blaming an innocent here, but unlikely */
if (kmod_loop_msg++ <
5)
printk(KERN_ERR
"request_module: runaway loop modprobe
%s\n",
module_name);
atomic_dec(&kmod_concurrent);
return
-ENOMEM;
}
ret = call_usermodehelper(modprobe_path, argv, envp,
1);
atomic_dec(&kmod_concurrent);
return
ret;
}
Linux把内核也看作一个模块。那么模块与模块之间如何进行交互呢,一种常用的方法就是共享变量和函数。但并不是模块中的每个变量和函数都能被共享,内核只把各个模块中主要的变量和函数放在一个特定的区段,这些变量和函数就统称为符号。到低哪些符号可以被共享? Linux内核有自己的规定。例如 EXPORT_SYMBOL_GPL(sysfs_create_link);
在fs/sysfs/symlink.c
其中宏定义EXPORT_SYMBOL()本身的含义是“移出符号”。为什么说是“移出”呢?因为这些符号本来是内核内部的符号,通过这个宏放在一个公开的地方,使得装入到内核中的其他模块可以引用它们。
实际上,仅仅知道这些符号的名字是不够的,还得知道它们在内核映像中的地址才有意义。因此,内核中定义了如下结构来描述模块的符号:
struct module_symbol
{
unsigned long value; /*符号在内核映像中的地址*/
const char *name; /*指向符号名的指针*/
};
从后面对EXPORT_SYMBOL宏的定义可以看出,连接程序(ld)在连接内核映像时将这个结构存放在一个叫做“__ksymtab”的区段中,而这个区段中所有的符号就组成了模块对外“移出”的符号表,这些符号可供内核及已安装的模块来引用。而其他“对内”的符号则由连接程序自行生成,并仅供内部使用。
与EXPORT_SYMBOL相关的定义在include/linux/module.h中:
#define __MODULE_STRING_1(x) #x
#define __MODULE_STRING(x) __MODULE_STRING_1(x)
#define __EXPORT_SYMBOL(sym, str)
\
const char __kstrtab_##sym[] \
__attribute__((section(".kstrtab"))) = str; \
const struct module_symbol __ksymtab_##sym \
__attribute__((section("__ksymtab"))) = \
{ (unsigned long)&sym, __kstrtab_##sym }
#if defined(MODVERSIONS) || !defined(CONFIG_MODVERSIONS)
#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
下面我们以EXPORT_SYMBOL(schedule)为例,来看一下这个宏的结果是什么。首先EXPORT_SYMBOL(schedule)的定义成了__EXPORT_SYMBOL(schedule, “schedule”)。而__EXPORT_SYMBOL()定义了两个语句,第一个语句定义了一个名为__kstrtab_ schedule的字符串,将字符串的内容初始化为“schedule”,并将其置于内核映像中的.kstrtab区段,注意这是一个专门存放符号名字符串的区段。第二个语句则定义了一个名为__kstrtab_ schedule的module_symbol结构,将其初始化为{&schedule,__kstrtab_ schedule}结构,并将其置于内核映像中的__ksymtab区段。这样,module_symbol结构中的域value的值就为schedule在内核映像中的地址,而指针name则指向字符串“schedule”。