Linux内核中的调试输出函数:printk详解
printk是Linux内核中最常用的调试函数之一,它用来向内核缓冲区或控制台输出调试信息,如变量的值,函数的执行流程,错误的原因等。printk的优点是简单易用,不需要额外的设备或驱动。printk的实现涉及到内核缓冲区,日志等级,格式化字符串等概念。在本文中,我们将介绍Linux内核调试技术之printk的原理和方法,并举例说明它们的使用方法和注意事项。
1、简介(基于s3c2440 linux)
在内核调试技术之中,最简单的就是printk的使用了,它的用法和C语言应用程序中的printf使用类似,在应用程序中依靠的是stdio.h中的库,而在linux内核中没有这个库,所以在linux内核中,使用这个printk就要对内核的实现有一定的了解。
printf和printk的区别:printk会在开头处加上””样式的字符,N的范围是0~7,表示这个信息的级别。
当printk(“”……);中的n
在内核文件中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 (includelinux) 定义了0~7这8个级别的名称
#define KERN_EMERG "" /* system is unusable */ #define KERN_ALERT "" /* action must be taken immediately */ #define KERN_CRIT "" /* critical conditions */ #define KERN_ERR "" /* error conditions */ #define KERN_WARNING "" /* warning conditions */ #define KERN_NOTICE "" /* normal but significant condition*/ #define KERN_INFO "" /* informational*/ #define KERN_DEBUG "" /* 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``/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 23``/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 25`` /work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 27``# ./firstdrvtest off` `/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 23``/work/LinuxDrives/ 20.printk_debug/first_drv.c first_drv_open 25``/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")会得到"abc", 再写入log_buf // 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息 // 调用硬件的write函数输出 release_console_sem call_console_drivers //从log_buf得到数据,算出打印级别 _call_console_drivers if ((msg_log_level 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
通过本文,我们了解了Linux内核调试技术之printk的原理和方法,它们可以用来实现对内核的调试和输出。我们应该根据实际需求选择合适的方法,并遵循一些基本原则,如使用正确的日志等级,使用正确的格式化字符串,使用正确的输出函数等。printk是Linux内核中最简单而有效的调试函数之一,它可以实现对内核的反馈和监控,也可以提升内核的可维护性和可扩展性。希望本文能够对你有所帮助和启发。
以上是Linux内核中的调试输出函数:printk详解的详细内容。更多信息请关注PHP中文网其他相关文章!

Linux系统管理员的主要任务包括系统监控与性能调优、用户管理、软件包管理、安全管理与备份、故障排查与解决、性能优化与最佳实践。1.使用top、htop等工具监控系统性能,并进行调优。2.通过useradd等命令管理用户账户和权限。3.利用apt、yum管理软件包,确保系统更新和安全。4.配置防火墙、监控日志、进行数据备份以确保系统安全。5.通过日志分析和工具使用进行故障排查和解决。6.优化内核参数和应用配置,遵循最佳实践提升系统性能和稳定性。

学习Linux并不难。1.Linux是一个开源操作系统,基于Unix,广泛应用于服务器、嵌入式系统和个人电脑。2.理解文件系统和权限管理是关键,文件系统是层次化的,权限包括读、写和执行。3.包管理系统如apt和dnf使得软件管理方便。4.进程管理通过ps和top命令实现。5.从基本命令如mkdir、cd、touch和nano开始学习,再尝试高级用法如shell脚本和文本处理。6.常见错误如权限问题可以通过sudo和chmod解决。7.性能优化建议包括使用htop监控资源、清理不必要文件和使用sy

Linux管理员的平均年薪在美国为75,000至95,000美元,欧洲为40,000至60,000欧元。提升薪资可以通过:1.持续学习新技术,如云计算和容器技术;2.积累项目经验并建立Portfolio;3.建立职业网络,拓展人脉。

Linux的主要用途包括:1.服务器操作系统,2.嵌入式系统,3.桌面操作系统,4.开发和测试环境。Linux在这些领域表现出色,提供了稳定性、安全性和高效的开发工具。

互联网运行不依赖单一操作系统,但Linux在其中扮演重要角色。Linux广泛应用于服务器和网络设备,因其稳定性、安全性和可扩展性受欢迎。

Linux操作系统的核心是其命令行界面,通过命令行可以执行各种操作。1.文件和目录操作使用ls、cd、mkdir、rm等命令管理文件和目录。2.用户和权限管理通过useradd、passwd、chmod等命令确保系统安全和资源分配。3.进程管理使用ps、kill等命令监控和控制系统进程。4.网络操作包括ping、ifconfig、ssh等命令配置和管理网络连接。5.系统监控和维护通过top、df、du等命令了解系统运行状态和资源使用情况。

介绍 Linux是一个强大的操作系统,由于其灵活性和效率,开发人员,系统管理员和电源用户都喜欢。但是,经常使用长而复杂的命令可能是乏味的

Linux适用于服务器、开发环境和嵌入式系统。1.作为服务器操作系统,Linux稳定高效,常用于部署高并发应用。2.作为开发环境,Linux提供高效的命令行工具和包管理系统,提升开发效率。3.在嵌入式系统中,Linux轻量且可定制,适合资源有限的环境。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

Atom编辑器mac版下载
最流行的的开源编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境