http://blog.csdn.net/fengel_cs/article/details/50468912
分析Linux内核启动流程时可以知道,在调用setup_arch函数之前就已经调用过printk函数了,但是这个时候的printk函数只是将打印信息放在缓存区中,并没有打印到控制台上,因为这个时候控制台还没有被初始化。
只有在start_kernel函数中的console_init函数被调用后,控制台才会被注册、初始化,printk函数打印的内容才会被真正地输出到屏幕上。如果想在console_init函数之前打印信息,需要调用early_printk函数。
下面是此函数的用法:
1. 配置内核
(1)Kernel hacking ---> Kernel low-level debugging functions --> Early printk
(2)在boot option中添加 earlyprintk项。类似于:Linux-CommandLine = root=/dev/mmcblk0p1 rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc ctp=2 skipcali=y ethmac=1C:6F:65:34:51:7E earlyprintk
(不传参数也能打印?)
2. 在需要打印调试信息的地方调用此函数
early_printk("------------xxx------------\n");
early_printk("------------xxx = %d------------\n", xxx);
3. 替代printk做调试,在kernel.h中定义printk宏,在printk.c中#undef printk 并调用printk_old()宏
#define printk_old() \
asmlinkage int printk(const char * fmt, ...) \
__attribute__ ((format (printf, 1, 2))) __cold;
asmlinkage int early_printk_new(const char *fmt, ...);
#define printk_new(fmt,args...) \
do{ \
early_printk("[xyc] [%s] %s:%d ",__func__,__FILE__,__LINE__); \
early_printk_new(fmt,##args); \
}while(0)
#define printk_new_2(fmt,args...) \
({ \
early_printk("[xyc] [%s] %s:%d ",__func__,__FILE__,__LINE__); \
early_printk_new(fmt,##args); \
})
#define printk(fmt,args...) printk_new(fmt,##args)
对于有些使用printk宏替换后不能编译通过的C源文件,可以在这部分取消宏,然后再次定义该宏
#undef printk
#define printk_old()
func()
{
.............
}
#define printk(fmt,args...) printk_new(fmt,##args)
扫描二维码关注公众号,回复:
1848710 查看本文章
asmlinkage void early_printk(const char *fmt, ...)
{
char buf[512];
int n;
va_list ap;
va_start(ap, fmt);
n = vscnprintf(buf, sizeof(buf), fmt, ap);
early_write(buf, n);
va_end(ap);
}
/*增加一个携带返回值的early_printk_new函数*/
asmlinkage int early_printk_new(const char *fmt, ...)
{
char buf[512];
int n;
va_list ap;
va_start(ap, fmt);
n = vscnprintf(buf, sizeof(buf), fmt, ap);
early_write(buf, n);
va_end(ap);
return n;
}