linux内核驱动初始化流程,linux 内核设备驱动初始化的实现(转)

解压,打印“Uncompressing Linux...”,调用gunzip(),打印"done, booting the kernel."然后call_kernel,执行解压后的kernel,经/arch//kernel/head.S调用start_kernel转入体系结构无关的通用C代码,在start_kernel()中完成了一系列系统初始化,设备及驱动的注册即在此时完成:

-------------------------

asmlinkage void __init start_kernel(void)

{

char * command_line;

extern struct kernel_param __start___param[], __stop___param[];

···········································································

printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line);

//打印内核命令行

parse_early_param();

parse_args("Booting kernel", command_line, __start___param, __stop___param - __start___param,

&unknown_bootoption);

//解析由BOOT传递的启动参数

···········································································

/* Do the rest non-__init'ed, we're now alive */

rest_init();

}

start_kernel()中的函数rest_init()将创建第一个核心线程kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND),调用init()函数:

static int init(void * unused)-------------------

{

·······················

do_basic_setup();

/*

* We try each of these until one succeeds.

*

* The Bourne shell can be used instead of init if we are

* trying to recover a really broken machine.

*/

if (execute_command) { //判断在启动时是否指定了init参数

//如果指定则执行用户init进程,成功将不会返回

run_init_process(execute_command);

printk(KERN_WARNING "Failed to execute %s.  Attempting " "defaults...\n", execute_command);

}

/*   如果没有指定init启动参数,则查找下面的目录init进程,成功将不会返回,否则打印出错信息   */

run_init_process("/sbin/init");

run_init_process("/etc/init");

run_init_process("/bin/init");

run_init_process("/bin/sh");

panic("No init found.  Try passing init= option to kernel.");

}

继而调用函数do_basic_setup()(此时与体系结构相关的部分已经初始化完了,现在开始初始化设备了):

/*

* Ok, the machine is now initialized. None of the devices * have been touched yet, but the CPU subsystem is up and * running, and memory and process management works.

*

* Now we can finally start doing some real work..

*/

static void __init do_basic_setup(void)-----------------

{

/* drivers will send hotplug events */

init_workqueues();

usermodehelper_init();

driver_init(); //建立设备模型子系统

#ifdef CONFIG_SYSCTL

sysctl_init();

#endif

/* Networking initialization needs a process context */

sock_init();

do_initcalls();   //系统初始化(包括设备,文件系统,内核模块等)

}

下面分析driver_init():

-------------------------

/**

* driver_init - initialize driver model.

*

* Call the driver model init functions to initialize their

* subsystems. Called early from init/main.c.

*/

void __init driver_init(void)

{

/* These are the core pieces */

devices_init();

-------------

int __init devices_init(void)

{

return subsystem_register(&devices_subsys);

}

subsystem_register():

buses_init();

classes_init();

firmware_init();

/* These are also core pieces, but must come after the * core core pieces.

*/

platform_bus_init();

system_bus_init();

cpu_dev_init();

memory_dev_init();

attribute_container_init();

}

---------------------------

extern initcall_t __initcall_start[], __initcall_end[];

static void __init do_initcalls(void)

{

initcall_t *call;

int count = preempt_count();

for (call = __initcall_start; call < __initcall_end; call++) {

··················

(*call)(); //调用一系列初始化函数

···················

}

__initcall_start和__initcall_end界定了存放初始化函数指针区域的起始地址,即从__initcall_start开始到__initcall_end结束的区域中存放了指向各个初始化函数的函数指针。 由 (*call)()完成各个部分的初始化工作,且便于扩充。具体实现如下:-----------------__initcall_start = .;

*(.initcall1.init) *(.initcall2.init) *(.initcall3.init) *(.initcall4.init) *(.initcall5.init) *(.initcall6.init) *(.initcall7.init) __initcall_end = .;

---------------------

#ifndef MODULE /*如果驱动模块静态编译进内核*/

···············································

/* initcalls are now grouped by functionality into separate

* subsections. Ordering inside the subsections is determined * by link order. * For backwards compatibility, initcall() puts the call in * the device init subsection.

*/

#define __define_initcall(level,fn) \

static initcall_t __initcall_##fn __attribute_used__ \

__attribute__((__section__(".initcall" level ".init"))) = fn

#define core_initcall(fn)  __define_initcall("1",fn) #define postcore_initcall(fn)  __define_initcall("2",fn) #define arch_initcall(fn)  __define_initcall("3",fn)

//此处初始化了设备

/*----eg:arch_initcall(at91sam9261_device_init)---

static int __init at91sam9261_device_init(void)

{

at91_add_device_udc();

at91_add_device_dm9000();

ebs3_add_input_buttons();

return platform_add_devices(at91sam9261_devices, ARRAY_SIZE(at91sam9261_devices));

}

------------------------*/

#define subsys_initcall(fn)  __define_initcall("4",fn) #define fs_initcall(fn)  __define_initcall("5",fn) #define device_initcall(fn)  __define_initcall("6",fn)

//此处初始化了静态编译的驱动模块

#define late_initcall(fn)  __define_initcall("7",fn)

#define __initcall(fn) device_initcall(fn)

/**

* module_init() - driver initialization entry point

* @x: function to be run at kernel boot time or module insertion

*

* module_init() will either be called during do_initcalls (if

* builtin) or at module insertion time (if a module).  There can only * be one per module.

*/

#define module_init(x) __initcall(x);

//静态编译的驱动模块作为device_initcall在内核启动就被do_initcalls

/**

* module_exit() - driver exit entry point

* @x: function to be run when driver is removed

*

* module_exit() will wrap the driver clean-up code

* with cleanup_module() when used with rmmod when

* the driver is a module.  If the driver is statically * compiled into the kernel, module_exit() has no effect. * There can only be one per module.

*/

#define module_exit(x) __exitcall(x);

#else /* MODULE如果驱动模块动态加载入内核*/

···············································

/* Each module must use one module_init(), or one no_module_init */

#define module_init(initfn) \

static inline initcall_t __inittest(void) \

{ return initfn; } \

int init_module(void) __attribute__((alias(#initfn)));

//insmod 是通过系统调用sys_init_module(const char *name_user, struct module *mod_user)

//将动态驱动模块载入到内核空间

/* This is only required if you want to be unloadable. */

#define module_exit(exitfn) \

static inline exitcall_t __exittest(void) \

{ return exitfn; } \

void cleanup_module(void) __attribute__((alias(#exitfn)));

-----------------------------

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值