C:LINUX如何来使用传入的参数



(由CONSOLE来使用的,既在CONSOLE注册时利用传进来的参数,这个是LINUX内核层的CONSOLE,注意与安桌层及文件系统层的PRINTK的区别。内核层只需要实现输出功能,但前者必须要实现输入输出,以及更复杂的功能)

LINUX内核源码版本:linux-3.0.86  

 

Console控制台:对于输入输出设备一个统一管理组件,可以认为是对计算机输入输出设备的封装。我们对于输入或输出不需要去了解其细节实现原理。只需要调用Console接口。

前一节准备好了参数资源console_cmdline这一节就是来实用的它了。对于命令行参数的实用是在console的注册函数中。既构建操控台中。

我们代码的console注册流程关系:s5p_serial_init->s3c24xx_serial_init->

platform_driver_register注册平台驱动,然后找到对应的平台设备就会会执行在注册平台驱动中的PROBE函数。s5p_serial_probe->s3c24xx_serial_probe->uart_add_one_port->

uart_configure_port->register_console(port->cons);根据上述流程我们需要得到port->是什么。得到这个代表了什么才能理解register_console函数里面的实现原理。通过查看代码可知

port->cons=s3c24xx_serial_console;

static struct uart_driver s3c24xx_uart_drv = {//注册平台驱动用的串口低层驱动函数

.owner = THIS_MODULE,

.driver_name = "s3c2410_serial",

.nr = CONFIG_SERIAL_SAMSUNG_UARTS,

#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE_SWITCH

.cons = NULL,

#else

.cons = S3C24XX_SERIAL_CONSOLE,

#endif

.dev_name = S3C24XX_SERIAL_NAME,

.major = S3C24XX_SERIAL_MAJOR,

.minor = S3C24XX_SERIAL_MINOR,

};

 

static struct console s3c24xx_serial_console = {

.name = S3C24XX_SERIAL_NAME=”ttySAC”,

.device = uart_console_device,

.flags = CON_PRINTBUFFER,

.index = -1,

.write = s3c24xx_serial_console_write,

.setup = s3c24xx_serial_console_setup,

.data = &s3c24xx_uart_drv,

};

因此register_consoles3c24xx_serial_console)接下来分析这个注册函数的原理。

console_drivers代表已注册了操控台链表。我们可以注册多个操控台。exclusive_console如果定义了打印操控台则这个标记会等于用.flags = CON_PRINTBUFFER,定义了的操控台。在printk函数中会判断这个标记,如果不等于它printk也不会从其它操控台输出数据。

if (preferred_console < 0 || bcon || !console_drivers)

preferred_console = selected_console;第一次注册操控台时,对于我们的串口操控台注册满足selected_console=0

 

/*

 * See if this console matches one we selected on

 * the command line.

 */

for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];

i++) {

if (strcmp(console_cmdline[i].name, newcon->name) != 0)

continue;

if (newcon->index >= 0 &&

    newcon->index != console_cmdline[i].index)

continue;

if (newcon->index < 0)//我们代码会执行这儿,因为index=-1

newcon->index = console_cmdline[i].index=0;

if (newcon->setup &&

 newcon->setup(newcon, console_cmdline[i].options) != 0)//根据传入的操控台数据来设置操控台。//newcon=s3c24xx_serial_console  console_cmdline[i].options)=115200n8

break;

/*setup=s3c24xx_serial_console_setup(struct console *co, char *options)根据传入的参数来重新初始化串口设备,具体的寄器配置,速率 位数 有无检验等。具体调用函数在s3c24xx_serial_ports中的s3c24xx_serial_ops.set_termios = s3c24xx_serial_set_termios,来完成上面相关的设置。

*/

newcon->flags |= CON_ENABLED;

newcon->index = console_cmdline[i].index=0;

if (i == selected_console) {

newcon->flags |= CON_CONSDEV;

preferred_console = selected_console=0;

}

上面是对传入的操控台初始化,以及调用

newcon->setup(newcon, console_cmdline[i].options) != 0)函数,这是很核心的代码。

 

if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {

newcon->next = console_drivers;

console_drivers = newcon;

if (newcon->next)

newcon->next->flags &= ~CON_CONSDEV;

} else {

newcon->next = console_drivers->next;

console_drivers->next = newcon;

}

上面代码完成对console_drivers链表的初始化。这个是注册了的操控台的一个链表,其它地方就是用这个变量来查找操控台的。比如PRINTK函数最后也是调用这个链表来查找要输出的串口号的具体硬件设备。

if (newcon->flags & CON_PRINTBUFFER) {

/*

 * console_unlock(); will print out the buffered messages

 * for us.

 */

spin_lock_irqsave(&logbuf_lock, flags);

con_start = log_start;

spin_unlock_irqrestore(&logbuf_lock, flags);

/*

 * We're about to replay the log buffer.  Only do this to the

 * just-registered console to avoid excessive message spam to

 * the already-registered consoles.

 */

exclusive_console = newcon;

}

上面代码说明当如果我们定义了CON_PRINTBUFFER操控台,则exclusive_console就等于它。在printk函数中判断了exclusive_console为真则不会调用console_driver中注册的所有操控来输出信息,而printk只会用exclusive_console定义的操控台。如果没有则会调用console_driver中定义了所有操控来输出信息。最后得出结论。console_driver

   代表了所有定义了的操控台。LINUX内核代码中实用操控台都是console_driver链表来操作的。同时printk函数输出信息则会判断我们定义的的操控台CON_PRINTBUFFER类型。通过上面系列处理得到注册操控台链表:console_driver

 

兴趣交流群抠抠: 461283592

你可能感兴趣的:(LINUX内核)