linux驱动启动时间有关问题

linux驱动启动时间问题
最近一个项目要搞linux驱动,但是以前没有搞过
所以有个问题研究了很久,还是没有搞清楚,想请教一下::
平时驱动开发直接用insmod插入模块即可
但是在嵌入式环境下,开机就要启动驱动,但是代码里面仍然是做成模块化的,所以我现在搞不清楚该驱动到底是在何处何时被初始化的:
比如::


static   int   __init   serial8250_init(void)
{
serial8250_isa_init_ports();
return   uart_register_driver(&serial8250_reg);
}

static   void   __exit   serial8250_exit(void)
{
uart_unregister_driver(&serial8250_reg);
}

module_init(serial8250_init);
module_exit(serial8250_exit);

上面是一个串口驱动,但是我追踪linux的启动代码是start_kernel,它调用了对应串口的控制台初始化函数 register_console(&serial8250_console);,难道通过调用控制台初始化函数就可以以后在某处调用串口的初始化函数__init   serial8250_init???


我还检察了开机自动加载文件modules.config和init.d/rcS,也没有发现启动相应的比如串口驱动,USB驱动等等驱动


想请高手指点一下,这些驱动到底是怎么启动的?



------解决方案--------------------
我虽然经验不多,大家一块学习,试图为你解释一下:
Linux内核有两种加载驱动程序的方法:一种就是系统启动之后通过insmod等函数加载;另一种就是系统启动时通过代码自身家在模块;
以module_init为例说明内核(2.4)如何在启动时加载模块的;module_init()宏被定义为:
#define module_init() __initcall(x);
#define __initcall(fn) static initcall_t __initcall_##fn__init_call=fn
你上面的预处理就变为:
static initcall_t __initcall_serial8250_init__init_call=serial8250_init
其中__init_call和initcall_t又被定义为
#define __init_call __attribute__((unused,__section__( ".initcall.init ")))
...
typedef init(*initcall_t)(void);
此时我们就可以看到了module_init(x)的真正意义在于在.initcall.init段的末使用空间中定义了一个指向x的函数指针。
对于.initcall.init段,系统依靠全局变量__initcall_start和__initcall_end纪录它的起始和结束地址。

然后我们看系统如何加载驱动程序的,在init/main.c文件中定义了函数do_initcalls如下:
static void __init do_initcalls(void)
{
initcall_t *call;
call=&__initcall_start;
do{
(*call)();
call++;
}while(call <&__initcall_end);
flush_sheduled_tasks();
}
这样在系统启动时,根据__initcall_start和__initcall_end依次初始化被编译在内核中的驱动程序。