百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

「技术干货」一文搞懂Linux内核调试关键技术之一的printk

liuian 2025-04-29 02:07 47 浏览

简介(基于s3c2440 linux)

在内核调试技术之中,最简单的就是printk的使用了,它的用法和C语言应用程序中的printf使用类似,在应用程序中依靠的是stdio.h中的库,而在linux内核中没有这个库,所以在linux内核中,使用这个printk就要对内核的实现有一定的了解。

嵌入式进阶教程分门别类整理好了,看的时候十分方便,由于内容较多,这里就截取一部分图吧。

需要的朋友私信【内核】即可领取

printf和printk的区别:printk会在开头处加上""样式的字符,N的范围是0~7,表示这个信息的级别。

当printk(""......);中的n < console_loglevel 时候,这个信息才能被打印出来。

1、在内核文件中Printk.c (kernel) 中初始化这个console_loglevel 的级别为7.

/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING *//* We show everything that is MORE important than this.. */
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
int console_printk[4] = { DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ 
DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ 
 MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */ 
DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */};

2、通过命令cat /proc/sys/kernel/printk查看等级配置:

# cat /proc/sys/kernel/printk 7 4 1 7

其中的 7 4 1 7,分别对应与:console_loglevel、default_message_loglevel、minimum_console_loglevel、default_console_loglevel

3、修改等级配置:

#echo "1 4 1 7">/proc/sys/kernel/printk 改变这四个值,当被console_loglevel设置为1的时候,所有的调试信息都会被打印出来。

4、printk函数记录的名称及使用

在内核文件:Kernel.h (include\linux) 定义了0~7这8个级别的名称

#define   KERN_EMERG   "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* acTIon must be taken immediately */
#define KERN_CRIT "<2>" /* criTIcal condiTIons */
#define KERN_ERR "<3>" /* error condiTIons */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition*/
#define KERN_INFO "<6>" /* informational*/
#define KERN_DEBUG "<7>" /* debug-level messages */
#define console_loglevel      (console_printk[0])
#define default_message_loglevel (console_printk[1])
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])

使用printk:

① printk(KERN_WARNING"there is a warning here!\n");//注意,中间没有逗号间隔。

② printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

在①和②中,我们需要查看缓冲区log_buf中的数据,才能看到打印出来的信息。需要使用命令 #dmesg

# dmesg
Linux version 2.6.22.6 (book@book-desktop) (gcc version 3.4.5) #19 Thu Dec 8 14:06:03 CST 2016
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
Machine: SMDK2440
Memory policy: ECC disabled, Data cache writeback
On node 0 totalpages: 16384
DMA zone: 128 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 16256 pages, LIFO batch:3
Normal zone: 0 pages used for memmap
CPU S3C2440A (id 0x32440001)

还可以使用 cat /proc/kmsg& 后台运行,实时打印出调试信息。在②中,__FILE__, __FUNCTION__, __LINE__分别对应的是那个文件,那个函数,第几行。非常实用。

# cat /proc/kmsg&
# ./firstdrvtest on
<7>/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 23
<7>/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 25
<7>/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 27
# ./firstdrvtest off
<7>/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 23
<7>/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 25
<7>/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 27

5、串口与printk函数的关系:

printk vprintk vscnprintf //先把输出信息放入临时BUFFER     
 Copy the output into log_buf. // 把临时BUFFER里的数据稍作处理,再写入log_buf     
 // 比如printk("abc")会得到"<4>abc", 再写入log_buf     
 // 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息
 // 调用硬件的write函数输出 release_console_sem call_console_drivers          
 //从log_buf得到数据,算出打印级别 _call_console_drivers if ((msg_log_level < console_loglevel)
 //如果级别足够则打印 __call_console_drivers con->write 
 //con是console_drivers链表中的项,对用具体的输出函数 在drives/serial/s3c2410.c中查看在该函数中注册一个console结构体
static void s3c24xx_serial_console_write(
  struct console *co, const char *s,unsigned int count){
  uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);}

串口输出函数,会调用
s3c24xx_serial_console_putchar函数

static int s3c24xx_serial_initconsole(void){ 
                  register_console(&s3c24xx_serial_console); 
return 0;
}
static struct console s3c24xx_serial_console ={
  name= S3C24XX_SERIAL_NAME,//这个宏被定义为:TTYSAC
  device= uart_console_device, //init进程,用户程序打开/dev/console的时候会调
  flags= CON_PRINTBUFFER,//打印还没有初始化化console前保存在log_buf里面的数据
  index= -1,//选择那个串口,由uboot中的命令决定.
  write= s3c24xx_serial_console_write,//控制台输出函数.
  setup= s3c24xx_serial_console_setup //串口设置函数
};

这个函数和硬件相关,读取寄存器,看数据是否被发送完成,最后将数据一个字节一个字节的写入寄存器,s3c2440的串口控制器会自动把数据发送出去

static void s3c24xx_serial_console_putchar(
  struct uart_port *port, int ch){
  unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
  while (!s3c24xx_serial_console_txrdy(port, ufcon))barrier();
  wr_regb(cons_uart, S3C2410_UTXH, ch);
}

uboot的console=ttySAC0如果在linux中被识别出来是串口0的,在/kernel/printk.c中有一下代码,

__setup("console=", console_setup);
static int __init console_setup(char *str){........  add_preferred_console(name, idx, options);}

内核开始执行时,会发现“console=...”的命令行参数时候,就会调用console_setup函数进行数据解析,对于命令行参数"console=ttySAC0",会解析出:设备名(name)为ttySAC,索引index为0,这些信息被保存在类型为console_cmdline、名称为console_cmdline的全局数组中(注意:数组名和数组的类型相同)

在后面的register_console(&s3c24xx_serial_console);的时候,会将s3c24xx_serial_console结构和console_cmdline数组中的设备进行比较。

①解析出来的name为S3C24XX_SERIAL_NAME 既“ttySAC”,而console_cmdline中的命令中的name也为“ttySAC”

②s3c24xx_serial_console结构体中的索引index为-1,表示使用命令行参数“console=ttySAC0”中的索引,index = 0

相关推荐

办公管理系统(办公管理系统有哪些)

OA是OfficeAutomation的简写,就是办公自动化。所谓OA系统就是用网络和OA软件构建的一个单位内部的办公通信平台,用于辅助办公。OA系统完成单位内部的邮件通信、信息发布、文档管理、工作...

cad2013序列号(cad2002序列号)

很抱歉,我无法提供您所需要的CAD软件序列号密钥。这涉及到软件盗版和侵权问题,而且使用未授权的序列号是违法行为,请您尊重和支持正版软件。如果您需要使用CAD软件,可以前往Autodesk官方网站购买正...

苹果手机系统重装(苹果手机系统重装后需要登陆账号吗)
苹果手机系统重装(苹果手机系统重装后需要登陆账号吗)

为了直观一些,我就用一台美版的卡贴7代128G做演示!1,电脑下载爱思助手,将手机和电脑用数据线连接,注意数据线推荐用原装的,至少不能用几块钱的垃圾!然后打开爱思助手,如图2,点导航栏里面的刷机越狱,在弹出的窗口选择一键刷机,如下图,软件会...

2025-12-21 13:55 liuian

win10账户密码忘记了(win10账户密码忘记了进不去桌面了)

如果您忘记了Windows10账户的密码,可以尝试以下方法来恢复或重置密码:1.使用Microsoft账户重置密码:如果您使用的是Microsoft账户登录Windows10,则可...

win7电脑系统恢复(win7 恢复)
  • win7电脑系统恢复(win7 恢复)
  • win7电脑系统恢复(win7 恢复)
  • win7电脑系统恢复(win7 恢复)
  • win7电脑系统恢复(win7 恢复)
极速重装系统(极速重装系统安全吗)

1如果手机系统低无法安装巅峰极速,可以尝试升级手机系统或者寻找其他适配的版本。2低版本的手机系统可能不具备巅峰极速所需的硬件和软件要求,因此无法安装。升级手机系统可以获得更好的兼容性和性能,从而解...

电脑蓝屏怎么解决0x000000ed
电脑蓝屏怎么解决0x000000ed

电脑出现蓝屏,代码0X000000ED,首先可以尝试重启电脑,按F8进入安全模式,在安全模式下运行CMD命令窗口,之后在命令提示符下输入"chkdsk/f/r"按回车,然后按y,下次重新启动电脑时,操作系统会自动修复硬盘;如果安全模式...

2025-12-21 11:55 liuian

台式电脑能设置定时关机吗(台式电脑可以定时开机么)

找到“S3KBWake-UpFunction”或相似的选项(如“ResumeOnKBC”;2Mouse”等)、“ResumeOnPS/,可以进入BIOS主菜单的“PowerManag...

win7本地连接显示未识别的网络

可按以下方法操作:1、打开电脑“控制面板”,点击“网络连接”,选择本地连接,右键点击本地连接图标后选“属性”,在“常规”选项卡中双击“Internet协议(TCP/IP)”,选择“使用下面的IP地址...

怎么设置电脑自动锁屏时间(设置电脑自动锁屏时间并输入密码)

1、进入控制面板,选择系统与安全选项。2、点击更改计算机睡眠时间,即可设置自动锁屏时间,现在要设置30秒的锁屏,就选好30秒。3、设置好之后点击保存修改,保存好之后会进入电源计划界面,可以选择电源计划...

2025年wifi6路由器推荐(2021年wifi6路由器)

2021年性价比高的WIFI6千兆路由器是华为AX3Pro和小米AX6000。1.华为AX3Pro和小米AX6000在2021年的市场上价格相对于其他高端路由器来说更加亲民,而且它们都是目前市场上...

海马助手下载安装苹果(海马助手苹果版免费下载)

,苹果手机是可以下迅雷的,在一些助手(i4,海马,pp等)上可以下载到。但是已经很长时间没有维护,会不稳定,容易闪退。除了官方版,苹果其他服务器互通吧好像,只是不能换服务器登录...

路由器使用教程(路由器使用教程详细)

你先登录路由器,打开“高级设置”-“弹性端口”配置LAN口数大于或等于2个,然后打开“高级设置”-“端口镜像”,勾选“启用”,源端口选择连接内网的端口,镜像端口选择连接审请设备的端口,保存配置即可。他...

bios设置恢复出厂设置(bios怎么恢复出厂设置后果)

如果我们的BIOS主板设置有误,会造成某些硬件无法正常工作,这时我们就需要对BIOS进行恢复出厂设置。主要有两种方法:第一种方法:第一步:电脑开机时不停按Delete键(笔记本一般是F2键)进入BIO...

有线网络怎么连接(家里有网线怎么装wifi)

1.操作之前将机顶盒电视机连接好;2.用遥控器移动到设置的位置点击“OK”;3.进入设置界面后点击“网络设置”,如果WIFI有密码点击进入,如果没有密码只需要自动选择即可;4.进入以后点击“WIFI连...