[Funkunux] Linux_2.6.22.6 内核start_kernel函数分析之console_init

在我的上一篇文章中,已经对start_kernel函数中的parse_init函数进行分析,该函数运行完后,可以得到如下三个变量:

saved_root_name="/dev/mtdblock3";
                                    
console_cmdline[0].name= "ttySAC";
console_cmdline[0].options= 0;
console_cmdline[0].idx= 0;
                                    
execute_command = "/linuxrc"

那么,这些参数都是在哪里被用到的呢?

我们先分析console_cmdline:

start_kernel 函数中调用了 console_init 函数:

void __init console_init(void)
{
	initcall_t *call;

	/* Setup the default TTY line discipline. */
	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);

	/*
	 * set up the console device so that later boot sequences can 
	 * inform about problems etc..
	 */
	call = __con_initcall_start;
	while (call < __con_initcall_end) {
		(*call)();
		call++;
	}
}
在这里我们注意到:__con_initcall_start 和 __con_initcall_end 这个地址,我们可以在vmlinux.lds中找到它的定义:

  __con_initcall_start = .;
   *(.con_initcall.init)
  __con_initcall_end = .;
显然,这两个地址之间存放的是 .con_initcall.init 段的内容,搜索得:

#define console_initcall(fn) \
	static initcall_t __initcall_##fn \
	__attribute_used__ __attribute__((__section__(".con_initcall.init")))=fn
也就是说,通过 console_initcall(fn) 这个宏,将一个 initcall_t 类型的函数指针 fn 存进 .con_initcall.init 这个段中。然后console_init函数中就会去调用这个函数 fn 。


我们继续搜索console_initcall,看看这个fn函数指针具体是哪一个。由于博主使用的开发板是s3c2440,所以搜索结果中有这么一项:

S3c2410.c (linux-2.6.22.6\drivers\serial):console_initcall(s3c24xx_serial_initconsole);

static int s3c24xx_serial_initconsole(void)
{
	struct s3c24xx_uart_info *info;
	struct platform_device *dev = s3c24xx_uart_devs[0];

	dbg("s3c24xx_serial_initconsole\n");

	/* select driver based on the cpu */

	if (dev == NULL) {
		printk(KERN_ERR "s3c24xx: no devices for console init\n");
		return 0;
	}

	if (strcmp(dev->name, "s3c2400-uart") == 0) {
		info = s3c2400_uart_inf_at;
	} else if (strcmp(dev->name, "s3c2410-uart") == 0) {
		info = s3c2410_uart_inf_at;
	} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
		info = s3c2440_uart_inf_at;
	} else if (strcmp(dev->name, "s3c2412-uart") == 0) {
		info = s3c2412_uart_inf_at;
	} else {
		printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
		return 0;
	}

	if (info == NULL) {
		printk(KERN_ERR "s3c24xx: no driver for console\n");
		return 0;
	}

	s3c24xx_serial_console.data = &s3c24xx_uart_drv;
	s3c24xx_serial_init_ports(info);

	register_console(&s3c24xx_serial_console);
	return 0;
}

显然 fn-> s3c24xx_serial_initconsole(),函数中调用了register_console(&s3c24xx_serial_console),

static struct console s3c24xx_serial_console =
{
	.name		= S3C24XX_SERIAL_NAME,
	.device		= uart_console_device,
	.flags		= CON_PRINTBUFFER,
	.index		= -1,
	.write		= s3c24xx_serial_console_write,
	.setup		= s3c24xx_serial_console_setup
};
<pre name="code" class="cpp">S3C24XX_SERIAL_NAME = "ttySAC" //和 <span style="font-family: Arial, Helvetica, sans-serif;">console_cmdline[0].name 一样</span>

 而且register_console函数中有这么一段: 

void register_console(struct console *console)
{
	...
	for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
			i++) {
		if (strcmp(console_cmdline[i].name, console->name) != 0)
			continue;
		if (console->index >= 0 &&
		    console->index != console_cmdline[i].index)
			continue;
		if (console->index < 0)
			console->index = console_cmdline[i].index;
		if (console->setup &&
		    console->setup(console, console_cmdline[i].options) != 0)
			break;
		console->flags |= CON_ENABLED;
		console->index = console_cmdline[i].index;
		if (i == selected_console) {
			console->flags |= CON_CONSDEV;
			preferred_console = selected_console;
		}
		break;
	}

	...
}
显然,当 console_cmdline[i].name 和 s3c24xx_serial_console.name相匹配,则 s3c24xx_serial_console.index = console_cmdline[i].index,且调用 s3c24xx_serial_console.setup(&s3c24xx_serial_console, console_cmdline[i].option),也即:

s3c24xx_serial_console_setup(&s3c24xx_serial_console, console_cmdline[0].option),在这里面对s3c24xx的设备串口进行初始化设置等。

console_cmdline分析到此。








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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值