首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

early printk实现流程

本文以ARM为例

一、功能说明

printk的log输出是由console实现(会在其他文章中说明)。由于在kernel刚启动的过程中,还没有为串口等设备等注册console(在device probe阶段实现),此时无法通过正常的console来输出log。

为此,linux提供了early console机制,用于实现为设备注册console之前的早期log的输出,对应console也称为boot console,简称bcon。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。而这个write方法也就是平台实现。

注意,这时候作为输出的串口设备是基于bootloader中已经初始化完成的。

early console机制有两种实现方式,早期的early_printk实现和后面的earlycon实现。在这里主要说明early_printk的实现方式.

early_printk与earlycon相比较为落后,其差异可以参考《earlycon实现流程》文章,建议使用earlycon的实现方式来做early console功能

二、需要打开的宏,如何使能

1、需要打开的宏

ENTRY(printch)定义在arch/arm/debug.S中,需要用这个宏来打开。

setup_early_printk的定义。解析cmdline中的early_printk参数并安装boot console。

early_printk输出函数的定义。

2、如何使能

在cmdline中添加“earlyprintk”字符串,如下:

三、如何使用

1、printascii、printk、early_print、early_printk的区别。

2、在setup.c中加对应例子并打印

比如:

(1)printascii(不建议使用)

(2)early_printk

(3)printk(通过early_console(bcon)来进行输出的)

(4)early_print(不建议使用)

内部包含了printascii和printk

加一条early_print测试一下会不会打印两次

四、early console代码流程

由于early_printk和printk都是基于early console的基础上实现。所以先说明early console的流程。

1、解析cmdline中的“early_printk参数”

arch/arm/kernel/early_printk.c

early_param和__setup相似,在cmdline中解析到”earlyprintk”字符串时,调用setup_early_printk。

__setup与early_param不同的是,early_param 宏注册的内核选项必须要在其他内核选项之前被处理。在函数start_kernel中,parse_early_param处理early_param定义的参数,parse_args处理__setup定义的参数,这里不详细说明,只需要知道当从cmdline中查找到对应字符串时,对应的setup函数会被调用。

2、setup_early_printk

arch/arm/kernel/early_printk.c

设置了early_console的实现。

调用register_console向kernel注册一个console(具体细节在console篇中说明)。

3、early_console_dev实现

arch/arm/kernel/early_printk.c

其中write方法用于实现console输出的入口,也early console的核心。

CON_PRINTBUFFER标识,表示注册这个console的时候,需要把printk的buf中的log通过这个console进行输出。

CON_BOOT标识,表示这是一个boot console(bcon)。当启动过程了注册其他非boot console的时候,需要先卸载掉这个console。

4、early_console_write也就是要实现printk和early_printk的核心

arch/arm/kernel/early_printk.c

调用到printch函数中。

5、printch实现

arch/arm/kernel/debug.S

addruart_current宏定义如下:

调用到addruart,也就是真正做写数据动作的位置,这也是平台上要实现的东西,也是说移植的核心就是实现这个函数。

以s5pv210为例

arch/arm/include/debug/s5pv210.S

注意在这里,只是基于bootloader中对于uart已经初始化完成并且可以正常使用的基础上,直接往uart的tx寄存器中写入数据,从而实现串口输出的目的。

至此,有两种方法通过early_console来输出log。

(1)直接调用early_console->write。

early_console->write(early_console, buf, n);

early_printk函数就是通过这种方法实现。

(2)通过标准printk接口调用到console的write函数。

printk函数就是通过这种方法实现。

下面会详细说明。

五、early_printk软件流程

kernel/printk/printk.c

直接通过early_console->write来进行console的输出。也就是上述四的内容。

六、printk软件流程(当early_console作为console)

当四中的register_console(&early_console_dev);完成之后,console子系统中的console_drivers就存在了early_console_dev这个console(具体参考“console”的文章)。

经过printk的标准调用之后

在call_console_drivers调用如下:

early_console_dev作为当前console_drivers一个con,其write函数也会被调用。

early_console_dev->write(con, text, len);

也就是上述第四节的内容,可以实现输出的目的。

七、Q&A

1、为什么就算early printk功能没有打开,只要串口console被注册,启动早期的log也会被打印出来?

printk buffer的存在。

串口console中包含CON_PRINTBUFFER标识,可以打印出printk buffer中的log。具体可以看register_console的实现。

八、backup

1、printascii软件流程(废弃)

arch/arm/kernel/debug.S

ENTRY(printascii)

addruart_current r3, r1, r2

ENDPROC(printascii)

同样也是通过addruart_current来实现。

具体参考《四、5实现》

2、 early_print软件流程(同样不推荐使用)

arch/arm/kernel/setup.c

通过printascii和printk来实现打印。

我今天才知道,我之所以漂泊就是在向你靠近。

--《廊桥遗梦》

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180306B0KBI400?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券