你知道Linux内核调试关键技术之一的printk?

合集下载

linux内核printk实现

linux内核printk实现
sizeof(printk_buf) - printed_len, fmt, args);
/*
* Copy the output into log_buf. If the caller didn't provide
* appropriate log level tags, we insert them here
wake_klogd |= log_start - log_end;
if (con_start == log_end)
break; /* Nothing to print */
_con_start = con_start;
_log_end = log_end; Flush */
DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
};
asmlinkage int printk(const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt); /* 可变参数,va_list为字符指针 */
* etc).
*
* The acquire_console_semaphore_for_printk() function
* will release 'logbuf_lock' regardless of whether it
* actually gets the semaphore or not.
}
static void call_console_drivers(unsigned start, unsigned end)

Linux中printk函数

Linux中printk函数
ntk("%llu", (unsigned long long)u64_var); s64,即(long long),必须用 %lld 或者 %llx 输出,如 : printk("%lld", (long long)s64_var); 如果 ( 变量类型 )<type> 的长度依赖一个配置选项 ( 例如: sector_t, blkcnt_t, phys_addr_t, resource_size_t) 或者 依赖 相关的体系结构(例如: tcflag_t ),使用一个可能最大类型的格 式说明符,并且显示转换它。如: printk("test: sector number/total blocks: %llu/%llu\n", (unsigned long long)sector, (unsigned long long)blockcount);
通过读写/proc/sys/kernel/printk文件可读取和修改控制台的日 志级别。查看这个文件的方法如下: #cat /proc/sys/kernel/printk 6 4 1 7 上面显示的4个数据分别对应控制台日志级别、默认的消息日志级 别、最低的控制台日志级别和默认的控制台日志级别。 可用下面的命令设置当前日志级别: # echo 8 > /proc/sys/kernel/printk 这样所有级别<8,(0-7)的消息都可以显示在控制台上. 编辑本段输出格式 printk函数可以指定输出的优先级: KERN_EMERG"<0>"/*紧急事件消息,系统崩溃之前提示,表示系统 不可用*/ KERN_ALERT"<1>"/*报告消息,表示必须立即采取措施*/ KERN_CRIT"<2>"/*临界条件,通常涉及严重的硬件或软件操作失 败*/ KERN_ERR"<3>"/*错误条件,驱动程序常用KERN_ERR来报告硬件的 错误*/ KERN_WARNING"<4>"/*警告条件,对可能出现问题的情况进行警告 */ KERN_NOTICE"<5>"/*正常但又重要的条件,用于提醒。常用于与 安全相关的消息*/ KERN_INFO"<6>"/*提示信息,如驱动程序启动时,打印硬件信息 */ KERN_DEBUG"<7>"/*调试级别的消息*/ 如果变量类型是 , 使用 prink 的格式说明符 : int %d 或者 %x( 注: %d 是十进制, %x 是十六进制 ) unsigned int %u 或者 %x long %ld 或者 %lx unsigned long %lu 或者 %lx long long %lld 或者 %llx unsigned long long %llu 或者 %llx size_t %zu 或者 %zx ssize_t %zd 或者 %zx 原始指针值必须用 %p 输出。 u64,即(unsigned long logn),必须用 %llu 或者 %llx 输 出,如:

linux printk日志级别

linux printk日志级别

linux printk日志级别(实用版)目录1.Linux printk 日志级别概述2.Linux printk 的日志级别分类3.如何设置和查看 Linux printk 日志级别4.Linux printk 日志级别的应用示例5.结论正文1.Linux printk 日志级别概述Linux printk 是 Linux 内核中的一个重要模块,主要用于打印内核缓冲区的调试信息。

printk 可以向控制台、文件或者网络发送调试信息。

printk 的日志级别用于控制打印信息的详细程度,以帮助开发者调试内核。

2.Linux printk 的日志级别分类Linux printk 的日志级别分为以下几类:- KERN_EMERGENCY: 紧急级别,表示系统出现严重问题,需要立即处理。

- KERN_ALERT: 警告级别,表示系统出现潜在问题,需要关注。

- KERN_CRITICAL: 严重级别,表示系统出现严重问题,但不需要立即处理。

- KERN_ERROR: 错误级别,表示系统出现错误,但不会影响系统运行。

- KERN_WARNING: 警告级别,表示系统出现潜在问题,但不会影响系统运行。

- KERN_NOTICE: 通知级别,表示系统出现某些特定事件,但不需要立即处理。

- KERN_INFO: 信息级别,表示系统运行状态的正常信息。

- KERN_DEBUG: 调试级别,表示系统运行的详细信息,供开发者调试使用。

3.如何设置和查看 Linux printk 日志级别要设置 Linux printk 日志级别,可以使用以下方法:- 修改/proc/sys/kernel/printk文件,可以直接编辑该文件,或者使用echo命令修改。

例如,要将日志级别设置为“KERN_DEBUG”,可以执行以下命令:```echo "KERN_DEBUG" > /proc/sys/kernel/printk```- 使用 sysctl 命令修改。

嵌入式Linux之Kernel(裁减移植)启动调试、打印技术 printascii(补充)、内核调试

嵌入式Linux之Kernel(裁减移植)启动调试、打印技术 printascii(补充)、内核调试

嵌入式系统搭建过程中,对于系统平台搭建工程师在完成Bootloader 的调试之后就进入Kernel 裁减移植的阶段,其中最重要的一步是Kernel 启动的调试,在调试Kernel 过程中通常遇到最常见的问题是启动异常:Uncompressing Linux....................................................................................... done, booting the kernel.( 挂死在此处)注意:这里是arch/arm/boot/compressed/head.S的解压过程,调用了decompress_kernel()(同目录下的misc.c)->include/asm-arm/arch-xxx/uncompress.h的putc()实现。

这是在uboot中初始化的,用的是物理地址,因为此时内核还没有起来。

而printascii则是调用了汇编。

printascii()位于arch/arm/kernel/debug.S,他需要调用虚拟地址,此虚拟地址通过machine_start提供,而相关的宏在include/asm/arch-xxx/debug-macro.S实现,这下明白了。

10-05-14添加:debug.s里面需要判断一下当前是否打开了mmu,然后指定uart的基址。

在解压阶段的head.s,mmu是1:1映射,目的是加快速度。

到了内核的head.s,就是真正的mmu了,此时就是虚拟地址了。

导致驱动异常(启动挂死)的原因有很多,如基于EVM 板的硬件做了修改(如更改了FLASH 空间大小、地址和型号,更改了SDRAM 、DDR SDRAM 空间大小、地址和型号,更改了晶振频率等),板卡ID号不支持等。

那么如何进行调试那,其实有两种调试技术比较有效。

Kernel 启动调试技术- 使用printascii() 函数跟踪start_kernel() 有没运行,在booting the kernel 之后Kernel 最先执行的是start_kernel() 函数,确认start_kernel() 有否执行就是在其开始代码段添加printascii("start_kernel …") ,如果串口没有打印出start_kernel …,说明start_kernel() 没有运行,那么可能的原因有Bootloader 配置的启动参数错误、 Kernel 加载到(DDR) SDRAM 的地址不正确, Kernel 编译时指定的(DDR) SDRAM 运行地址不正确等。

打印调试技术 printk klogd dmesg(解决打印信息的问题)

打印调试技术 printk klogd dmesg(解决打印信息的问题)

4.2.1. printk#includeprintk(KERN_CRIT"error %s,%i",__FILE__,__LINE__);注:1). printk函数中能够指定优先级,假如printk没有指定优先级,采用默认优先级,DEFAULT_MESSAGE_LEVEL,其值在kernel/printk.c.头文档linux/printk.h中宏定义了8个级别,0-8从高到低分别是:KERN_EMERG, KERNEL_ALERT, KERN_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG2). 当printk指定的优先级小于指定的控制台优先级console_loglevel时,调试消息就显示在控制台虚拟终端。

缺省的console_loglevel值是DEFAULT_CONSOLE_LOGLEVEL。

.也能够使用系统调用sys_syslog或klogd -c来修改console_loglevel值。

.在新版本中,也能够直接通过文档/proc/sys/kernel/printk修改,这个文档包含4个整数值,前两个表示系统当前的优先级和缺省优先级。

能够直接echo 8 > /proc/sys/kernel/printk.也能够指定显示在其他控制台,通过调用ioctl(TIOCLINUX)或shell命令setconsole来配置。

.假如运行了klogd和syslogd,则printk打印到var/log/messages。

. 用打印调试最常用的调试技术是监视, 在应用程序编程当中是通过在合适的地方调用printf 来实现. 在你调试内核代码时, 你可以通过printk 来达到这个目的.一个不同是printk 允许你根据消息的严重程度对其分类, 通过附加不同的记录级别或者优先级在消息上. 你常常用一个宏定义来指示记录级别. 例如, KERN_INFO, 我们之前曾在一些打印语句的前面看到过, 是消息记录级别的一种可能值. 记录宏定义扩展成一个字串, 在编译时与消息文本连接在一起; 这就是为什么下面的在优先级和格式串之间没有逗号的原因. 这里有2 个printk 命令的例子, 一个调试消息, 一个紧急消息:printk(KERN_DEBUG "Here I am: %s:%i/n", __FILE__, __LINE__);printk(KERN_CRIT "I'm trashed; giving up on %p/n", ptr);有8 种可能的记录字串, 在头文件<linux/kernel.h> 里定义; 我们按照严重性递减的顺序列出它们:KERN_EMERG用于紧急消息, 常常是那些崩溃前的消息.KERN_ALERT需要立刻动作的情形.KERN_CRIT严重情况, 常常与严重的硬件或者软件失效有关.KERN_ERR用来报告错误情况; 设备驱动常常使用KERN_ERR 来报告硬件故障.KERN_WARNING有问题的情况的警告, 这些情况自己不会引起系统的严重问题.KERN_NOTICE正常情况, 但是仍然值得注意. 在这个级别一些安全相关的情况会报告.KERN_INFO信息型消息. 在这个级别, 很多驱动在启动时打印它们发现的硬件的信息.KERN_DEBUG用作调试消息.每个字串( 在宏定义扩展里)代表一个在角括号中的整数. 整数的范围从0 到7, 越小的数表示越大的优先级.一条没有指定优先级的printk 语句缺省是DEFAULT_MESSAGE_LOGLEVEL, 在kernel/printk.c 里指定作为一个整数. 在2.6.10 内核中, DEFAULT_MESSAGE_LOGLEVEL 是KERN_WARNING, 但是在过去已知是改变的.基于记录级别, 内核可能打印消息到当前控制台, 可能是一个文本模式终端, 串口, 或者是一台并口打印机. 如果优先级小于整型值console_loglevel, 消息被递交给控制台, 一次一行( 除非提供一个新行结尾, 否则什么都不发送). 如果klogd 和syslogd 都在系统中运行, 内核消息被追加到/var/log/messages (或者另外根据你的syslogd 配置处理), 独立于console_loglevel. 如果klogd 没有运行, 你只有读/proc/kmsg ( 用dmsg 命令最易做到)将消息取到用户空间. 当使用klogd 时, 你应当记住, 它不会保存连续的同样的行; 它只保留第一个这样的行, 随后是, 它收到的重复行数.变量console_loglevel 初始化成DEFAULT_CONSOLE_LOGLEVEL, 并且可通过sys_syslog 系统调用修改. 一种修改它的方法是在调用klogd 时指定-c 开关, 在klogd 的manpage 里有指定. 注意要改变当前值, 你必须先杀掉klogd, 接着使用-c 选项重启它. 另外, 你可写一个程序来改变控制台记录级别. 你会发现这样一个程序的版本在由O' Reilly 提供的FTP 站点上的miscprogs/setlevel.c. 新的级别指定未一个整数, 在1 和8 之前, 包含1 和8. 如果它设为1, 只有0 级消息( KERN_EMERG )到达控制台; 如果它设为8, 所有消息, 包括调试消息, 都显示.也可以通过文本文件/proc/sys/kernel/printk 读写控制台记录级别. 这个文件有4 个整型值: 当前记录级别, 适用没有明确记录级别的消息的缺省级别, 允许的最小记录级别, 以及启动时缺省记录级别. 写一个单个值到这个文件就改变当前记录级别成这个值; 因此, 例如, 你可以使所有内核消息出现在控制台, 通过简单地输入:# echo 8 > /proc/sys/kernel/printk现在应当清楚了为什么hello.c 例子使用KERN_ALERT 标志; 它们是要确保消息会出现在控制台上.4.2.2. 重定向控制台消息Linux 在控制台记录策略上允许一些灵活性, 它允许你发送消息到一个指定的虚拟控制台(如果你的控制台使用的是文本屏幕). 缺省地, 这个"控制台"是当前虚拟终端. 为了选择一个不同地虚拟终端来接收消息, 你可对任何控制台设备调用ioctl(TIOCLINUX). 下面的程序, setconsole, 可以用来选择哪个控制台接收内核消息; 它必须由超级用户运行, 可以从misc-progs 目录得到.下面是全部程序. 应当使用一个参数来指定用以接收消息的控制台的编号.int main(int argc, char **argv){char bytes[2] = {11,0}; /* 11 is the TIOCLINUX cmd number */if (argc==2) bytes[1] = atoi(argv[1]); /* the chosen console */else {fprintf(stderr, "%s: need a single arg/n",argv[0]); exit(1); } if (ioctl(STDIN_FILENO, TIOCLINUX, bytes)<0) { /* use stdin */ fprintf(stderr,"%s: ioctl(stdin, TIOCLINUX): %s/n",argv[0], strerror(errno));exit(1);}exit(0);}setconsole 使用特殊的ioctl 命令TIOCLINUX, 来实现特定于linux 的功能. 为使用TIOCLINUX, 你传递它一个指向字节数组的指针作为参数. 数组的第一个字节是一个数, 指定需要的子命令, 下面的字节是特对于子命令的. 在setconsole 里, 使用子命令11, 下一个字节(存于bytes[1])指定虚拟控制台. TIOCLINUX 的完整描述在内核源码的drivers/char/tty_io.c 里.4.2.3. 消息是如何记录的printk 函数将消息写入一个__LOG_BUF_LEN 字节长的环形缓存, 长度值从4 KB 到1 MB, 由配置内核时选择. 这个函数接着唤醒任何在等待消息的进程, 就是说, 任何在系统调用中睡眠或者在读取/proc/kmsg 的进程. 这2 个日志引擎的接口几乎是等同的, 但是注意, 从/proc/kmsg 中读取是从日志缓存中消费数据, 然而syslog 系统调用能够选择地在返回日志数据地同时保留它给其他进程. 通常, 读取/proc 文件容易些并且是klogd 的缺省做法. dmesg 命令可用来查看缓存的内容, 不会冲掉它; 实际上, 这个命令将缓存区的整个内容返回给stdout, 不管它是否已经被读过.在停止klogd 后, 如果你偶尔手工读取内核消息, 你会发现/proc 看起来象一个FIFO, 读者阻塞在里面, 等待更多数据. 显然, 你无法以这种方式读消息, 如果klogd 或者其他进程已经在读同样的数据, 因为你要竞争它.如果环形缓存填满, printk 绕回并在缓存的开头增加新数据, 覆盖掉最老的数据. 因此, 这个记录过程会丢失最老的数据. 这个问题相比于使用这样一个环形缓存的优点是可以忽略的. 例如, 环形缓存允许系统即便没有一个日志进程也可运行, 在没有人读它的时候可以通过覆盖旧数据浪费最少的内存. Linux 对于消息的解决方法的另一个特性是, printk 可以从任何地方调用, 甚至从一个中断处理里面, 没有限制能打印多少数据. 唯一的缺点是可能丢失一些数据.如果klogd 进程在运行, 它获取内核消息并分发给syslogd, syslogd 接着检查/etc/syslog.conf 来找出如何处理它们. syslogd 根据一个设施和一个优先级来区分消息; 这个设施和优先级的允许值在<sys/syslog.h> 中定义. 内核消息由LOG_KERN 设施来记录, 在一个对应于printk 使用的优先级上(例如, LOG_ERR 用于KERN_ERR 消息). 如果klogd 没有运行, 数据保留在环形缓存中直到有人读它或者缓存被覆盖.如果你要避免你的系统被来自你的驱动的监视消息击垮, 你或者给klogd 指定一个-f (文件) 选项来指示它保存消息到一个特定的文件, 或者定制/etc/syslog.conf 来适应你的要求. 但是另外一种可能性是采用粗暴的方式: 杀掉klogd 和详细地打印消息在一个没有用到的虚拟终端上,[13 ] 或者从一个没有用到的xterm 上发出命令cat /proc/kmsg.4.2.4. 打开和关闭消息在驱动开发的早期, printk 非常有助于调试和测试新代码. 当你正式发行驱动时, 换句话说, 你应当去掉, 或者至少关闭, 这些打印语句. 不幸的是, 你很可能会发现, 就在你认为你不再需要这些消息并去掉它们时, 你要在驱动中实现一个新特性(或者有人发现了一个bug), 你想要至少再打开一个消息. 有几个方法来解决这2 个问题, 全局性地打开或关闭你地调试消息和打开或关闭单个消息.这里我们展示一种编码printk 调用的方法, 你可以单独或全局地打开或关闭它们; 这个技术依靠定义一个宏, 在你想使用它时就转变成一个printk (或者printf)调用.每个printk 语句可以打开或关闭, 通过去除或添加单个字符到宏定义的名子.所有消息可以马上关闭, 通过在编译前改变CFLAGS 变量的值.同一个print 语句可以在内核代码和用户级代码中使用, 因此对于格外的消息, 驱动和测试程序能以同样的方式被管理.下面的代码片断实现了这些特性, 直接来自头文件scull.h:#undef PDEBUG /* undef it, just in case */#ifdef SCULL_DEBUG# ifdef __KERNEL__/* This one if debugging is on, and kernel space */# define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull: " fmt, ## args)# else/* This one for user space */# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)# endif#else# define PDEBUG(fmt, args...) /* not debugging: nothing */#endif#undef PDEBUGG #define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */符号PDEBUG 定义和去定义, 取决于SCULL_DEBUG 是否定义, 和以何种方式显示消息适合代码运行的环境: 当它在内核中就使用内核调用printk, 在用户空间运行就使用libc 调用fprintf 到标准错误输出. PDEBUGG 符号, 换句话说, 什么不作; 他可用来轻易地"注释" print 语句, 而不用完全去掉它们.为进一步简化过程, 添加下面的行到你的makfile 里:# Comment/uncomment the following line to disable/enable debuggingDEBUG = y# Add your debugging flag (or not) to CFLAGSifeq ($(DEBUG),y)DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlineselseDEBFLAGS = -O2endifCFLAGS += $(DEBFLAGS)本节中出现的宏定义依赖gcc 对ANSI C 预处理器的扩展, 支持带可变个数参数的宏定义. 这个gcc 依赖不应该是个问题, 因为无论如何内核固有的非常依赖于gcc 特性. 另外, makefile 依赖GNU 版本的make; 再一次, 内核也依赖GNU make, 所以这个依赖不是问题.如果你熟悉C 预处理器, 你可以扩展给定的定义来实现一个"调试级别"的概念, 定义不同的级别, 安排一个整数(或者位掩码)值给每个级别, 以便决定它应当多么详细.但是每个驱动有它自己的特性和监视需求. 好的编程技巧是在灵活性和效率之间选择最好的平衡, 我们无法告诉你什么是最好的. 记住, 预处理器条件(连同代码中的常数表达式)在编译时执行, 因此你必须重新编译来打开或改变消息. 一个可能的选择是使用C 条件句, 它在运行时执行, 因而, 能允许你在出现执行时打开或改变消息机制. 这是一个好的特性, 但是它在每次代码执行时需要额外的处理, 这样即便消息给关闭了也会影响效率. 有时这个效率损失无法接受.本节出现的宏定义已经证明在多种情况下是有用的, 唯一的缺点是要求在任何对它的消息改变后重新编译.4.2.5. 速率限制如果你不小心, 你会发现自己用printk 产生了上千条消息, 压倒了控制台并且, 可能地, 使系统日志文件溢出. 当使用一个慢速控制台设备(例如, 一个串口), 过量的消息速率也能拖慢系统或者只是使它不反应了. 非常难于着手于系统出错的地方, 当控制台不停地输出数据. 因此, 你应当非常注意你打印什么, 特别在驱动的产品版本以及特别在初始化完成后. 通常, 产品代码在正常操作时不应当打印任何东西; 打印的输出应当是指示需要注意的异常情况.另一方面, 你可能想发出一个日志消息, 如果你驱动的设备停止工作. 但是你应当小心不要做过了头. 一个面对失败永远继续的傻瓜进程能产生每秒上千次的尝试; 如果你的驱动每次都打印"my device is broken", 它可能产生大量的输出, 如果控制台设备慢就有可能霸占CPU -- 没有中断用来驱动控制台, 就算是一个串口或者一个行打印机.在很多情况下, 最好的做法是设置一个标志说, "我已经抱怨过这个了", 并不打印任何后来的消息只要这个标志设置着. 然而, 有几个理由偶尔发出一个"设备还是坏的"的提示. 内核已经提供了一个函数帮助这个情况:int printk_ratelimit(void);这个函数应当在你认为打印一个可能会常常重复的消息之前调用. 如果这个函数返回非零值, 继续打印你的消息, 否则跳过它. 这样, 典型的调用如这样:if (printk_ratelimit())printk(KERN_NOTICE "The printer is still on fire/n");printk_ratelimit 通过跟踪多少消息发向控制台而工作. 当输出级别超过一个限度, printk_ratelimit 开始返回0 并使消息被扔掉.printk_ratelimit 的行为可以通过修改/proc/sys/kern/printk_ratelimit( 在重新使能消息前等待的秒数) 和/proc/sys/kernel/printk_ratelimit_burst(限速前可接收的消息数)来定制.4.2.6. 打印设备编号偶尔地, 当从一个驱动打印消息, 你会想打印与感兴趣的硬件相关联的设备号. 打印主次编号不是特别难, 但是, 为一致性考虑, 内核提供了一些实用的宏定义( 在<linux/kdev_t.h> 中定义)用于这个目的:int print_dev_t(char *buffer, dev_t dev);char *format_dev_t(char *buffer, dev_t dev);两个宏定义都将设备号编码进给定的缓冲区; 唯一的区别是print_dev_t 返回打印的字符数, 而format_dev_t 返回缓存区; 因此, 它可以直接用作printk 调用的参数, 但是必须记住printk 只有提供一个结尾的新行才会刷行. 缓冲区应当足够大以存放一个设备号; 如果64 位编号在以后的内核发行中明显可能, 这个缓冲区应当可能至少是20 字节长.总结:(1)所有系统信息是输出到ring buffer中去的.dmesg所显示的内容也是从ring buffer中读取的.(2)linux系统中/etc/init.d/sysklogd会启动2个守护进程:klogd&&syslogd(3)klogd是负责读取内核信息的,有2种方式:syslog()系统调用(这个函数用法比较全,大家去man一下看看)直接的对/proc/kmsg进行读取(再这提一下,/proc/kmsg是专门输出内核信息的地方)(4)klogd的输出结果会传送给syslogd进行处理,syslogd会根据/etc/syslog.conf的配置把log信息输出到/var/log/下的不同文件中。

linux内核的打印printk的级别

linux内核的打印printk的级别

linux内核的打印printk的级别调整内核printk打印级别--减少启动时的打印信息2012-02-01 16:52:26| 分类:工作生活 | 标签:linux |字号大中小订阅有时调试内核模块,打印信息太多了,可以通过修改/proc/sys/kernel/printk文件内容来控制。

默认设置是6 4 1 7 # cat /proc/sys/kernel/printk7 4 1 7该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。

关于不同日志级别的更多信息,请查阅syslog(2)联机帮助。

上面显示的4个数据分别对应:控制台日志级别:优先级高于该值的消息将被打印至控制台默认的消息日志级别:将用该优先级来打印没有优先级的消息最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)默认的控制台日志级别:控制台日志级别的缺省值数值越小,优先级越高其实这四个值是在kernel/printk.c 中被定义的,如下: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 */};内核通过printk() 输出的信息具有日志级别,日志级别是通过在printk() 输出的字符串前加一个带尖括号的整数来控制的,如printk("<6>Hello, world!\n");。

内核中共提供了八种不同的日志级别,在 linux/kernel.h 中有相应的宏对应。

linux printk日志级别

linux printk日志级别

linux printk日志级别摘要:1.Linux printk 概述2.日志级别的定义与作用3.printk 的日志级别设置4.常见日志级别的使用5.总结正文:【1.Linux printk 概述】printk 是Linux 内核中的一个重要模块,主要用于打印内核缓冲区的调试信息。

printk 可以向控制台、文件或者网络发送调试信息,从而帮助开发者定位和解决问题。

printk 的日志功能强大且灵活,可以根据需要设置不同的日志级别。

【2.日志级别的定义与作用】日志级别是printk 中的一种分类方式,用于控制打印出的日志信息的详细程度。

日志级别从低到高依次为:DEBUG、INFO、NOTICE、WARNING、ERROR、CRIT、ALERT、EMERG。

级别越高,打印出的日志信息越详细。

通过设置日志级别,可以有效地过滤掉不必要的日志信息,提高调试效率。

【3.printk 的日志级别设置】printk 的日志级别设置可以通过内核参数、系统调用和编程方式实现。

(1)内核参数:通过修改/proc/sys/kernel/printk 文件,可以设置系统的默认日志级别。

例如,要将默认日志级别设置为DEBUG,可以执行以下命令:```echo "DEBUG" > /proc/sys/kernel/printk```(2)系统调用:通过调用sys_set_printk_level 函数,可以更改当前进程的日志级别。

例如,将以下代码添加到应用程序中,将日志级别设置为DEBUG:```c#include <linux/printk.h>#include <linux/kernel.h>int main() {sys_set_printk_level(DEFAULT_PRINTK_LEVEL, "DEBUG");//...}```(3)编程方式:在C 语言程序中,可以使用printk 函数打印日志。

printk使用方法

printk使用方法

printk使用方法引言:printk是Linux内核中用于输出调试和日志信息的函数。

本文将介绍printk的使用方法,包括语法、参数和示例等内容。

一、语法printk的语法如下:int printk(const char *fmt, ...)其中,参数fmt是一个格式化字符串,可以包含占位符,占位符用于指定输出的格式和值。

占位符的常用格式如下:%c:输出一个字符%d:输出一个有符号十进制整数%u:输出一个无符号十进制整数%x:输出一个无符号十六进制整数%s:输出一个字符串二、参数printk函数的参数可以是一个格式化字符串,也可以是多个参数与格式化字符串一起使用。

参数的个数和类型需要与格式化字符串中的占位符相匹配。

三、示例下面是一些使用printk的示例:1. 输出一个字符:char ch = 'A';printk("字符:%c\n", ch);输出结果:字符:A2. 输出一个有符号十进制整数:int num = -123;printk("整数:%d\n", num);输出结果:整数:-1233. 输出一个无符号十进制整数:unsigned int uNum = 456;printk("无符号整数:%u\n", uNum);输出结果:无符号整数:4564. 输出一个无符号十六进制整数:unsigned int hexNum = 0xABC;printk("十六进制整数:%x\n", hexNum);输出结果:十六进制整数:abc5. 输出一个字符串:const char *str = "Hello World!";printk("字符串:%s\n", str);输出结果:字符串:Hello World!四、常见问题1. 如何输出多个参数?如果需要输出多个参数,可以在格式化字符串中使用多个占位符,并依次传入对应的参数。

early_printk 原理

early_printk 原理

early_printk 原理early_printk是一种在Linux内核启动早期提供调试信息输出的机制。

在Linux内核启动的早期阶段,系统的大部分功能还没有初始化,因此无法使用常规的日志输出机制。

而early_printk则提供了一种能够在这个阶段输出调试信息的方式,帮助开发者在内核启动过程中进行调试和排错。

early_printk的原理是通过使用早期初始化的串行控制台来输出调试信息。

在Linux内核启动的早期阶段,还没有初始化硬件设备和驱动程序,因此无法使用常规的控制台输出。

为了解决这个问题,Linux内核在早期阶段会初始化一个叫做earlycon的串行控制台,用于输出早期阶段的调试信息。

early_printk的工作流程如下:1. 在内核启动的早期阶段,early_printk会被初始化并注册为一个字符设备。

2. early_printk的初始化过程会尝试初始化一个可用的串行控制台,例如串口、VGA控制台等。

3. 一旦找到可用的串行控制台,early_printk就可以使用该控制台进行输出操作。

4. 开发者可以通过在内核代码中使用early_printk函数来输出调试信息。

5. early_printk的输出会被重定向到已经初始化的串行控制台,从而实现调试信息的显示。

early_printk的优点是可以在内核启动的早期阶段输出调试信息,帮助开发者快速定位和解决问题。

由于早期阶段的初始化过程相对简单,因此early_printk的实现也相对简单。

另外,early_printk 输出的调试信息可以实时显示在控制台上,方便开发者进行调试。

然而,early_printk也存在一些限制和注意事项。

首先,由于早期阶段的初始化过程还没有完成,因此early_printk只能使用一些简单的输出函数,不能使用复杂的格式化输出。

其次,early_printk 的输出只能显示在已经初始化的串行控制台上,不能输出到其他设备或者网络中。

Linux内核打印函数printk的使用说明

Linux内核打印函数printk的使用说明

Linux内核打印函数printk的使用说明printk函数We used the printk function in earlier chapters with the simplifying assumption that it works like printf. Now it's time to introduce some of the differences.我们在前面章节中简单地把printk当作printf函数来使用。

现在是时候来介绍它的一些不同之处了。

One of the differences is that printk lets you classify messages according to their severity by associating different loglevels, or priorities, with the messages. You usually indicate the loglevel with a macro. For example, KERN_INFO, which we saw prepended to some of the earlier print statements, is one of the possible loglevels of the message. The loglevel macro expands to a string, which is concatenated to the message text at compile time; that's why there is no comma between the priority and the format string in the following examples. Here are two examples of printk commands, a debug message and a critical message:其中一个不同点是,printk允许你按照相关的记录级或优先级将消息严格分类。

Linux下使用printk()的方法

Linux下使用printk()的方法

Linux下使用printk()的方法导读:如果你有了解过Linux内核,那么你应该对printk函数有了一定的了解,那么对于没接触过printk函数的朋友来说,printk()究竟要如何使用呢?下面小编通过一个例子来讲解printk()的使用,以便大家有更深入的了解。

实例:新建hello.c#include 《linux/kernel.h》#include 《linux/module.h》int init_module(void){printk(KERN_INFO “Welcome.。

.。

\n”);return 0;}void cleanup_module(void){printk(KERN_INFO “Bye.。

.\n”);}然后在同一目录下编写Makefile:obj-m := hello.oall:make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd)clean:-rm *.o *.ko Mod* mod* *.mod.c进入终端,切换到对应目录下执行make编译完成后会得到hello.ko//hello.ko就是编译好的模块执行sudo insmod hello.ko //加载模块执行lsmod 可以察看当前已经加载的模块,如果hello.ko已经加载,那么执行完lsmod后就可以看到已经加载好的hello.ko执行dmesg就可以察看printk()函数的输出,此时可以看到打印出来的Welcome.。

这个信息其实是保存在/var/log/syslog这个文件中的,查看这个文件也同样能看到输出的信息Welcom.。

测试完毕后执行sudo rmmod hello卸载模块即可上面就是Linux使用printk()的方法介绍了,本文只是简单的通过一个例子来讲解printk函数的用法,你可以上网了解更多的printk()的用法。

printk用法

printk用法

printk用法
printk是Linux内核中用于输出日志信息的函数,可用于debug 和诊断程序的运行问题。

printk的用法包括:
1. 头文件引入:需要包含<linux/kernel.h>头文件才能使用printk函数。

2. 日志级别控制:printk函数的第一个参数是日志级别,按照重要程度从高到低分别为KERN_EMERG、KERN_ALERT、KERN_CRIT、KERN_ERR、KERN_WARNING、KERN_NOTICE、KERN_INFO和KERN_DEBUG。

可通过修改内核配置文件来控制输出哪些级别的日志信息。

3. 输出格式:printk函数的使用方式类似于printf,可使用%s、%d、%x等格式化输出参数,也可使用转义符号如
和t来控制输出格式。

4. 输出位置:printk函数默认将日志信息输出到系统日志缓存中,也可通过将第三个参数设置为console来将日志信息输出到控制台。

5. 日志信息量控制:可通过设置内核参数来控制系统最多能保存多少日志信息,以避免系统资源被消耗完。

6. 优化:由于printk函数的调用频繁,需要注意优化,如使用缓存来减少系统调用次数、控制输出频率等。

- 1 -。

printk 默认级别

printk 默认级别

printk 默认级别1. 什么是 printk?printk 是一个在 Linux 内核中用于输出调试信息和日志的函数。

它可以在内核代码中使用,也可以在驱动程序和模块中使用。

printk 函数的输出可以显示在控制台上,也可以写入系统日志。

2. printk 的默认级别是什么?printk 函数有不同的级别,用于指定输出信息的重要程度。

在默认情况下,printk 的默认级别是 KERN_WARNING,即警告级别。

这意味着只有警告级别及以上的消息才会被输出。

3. printk 的级别有哪些?printk 的级别按照重要程度从高到低可以分为以下几个级别:3.1. KERN_EMERG这是最高级别的错误消息,表示系统已经无法使用。

这种情况下,内核通常会触发崩溃转储,以便进行调试和分析。

3.2. KERN_ALERT这是一个非常严重的错误消息,表示系统可能无法正常工作。

一般情况下,这种错误会引起管理员的注意并需要立即采取行动来解决问题。

3.3. KERN_CRIT这个级别的错误消息表示系统出现了严重的错误,但仍然可以继续运行。

通常情况下,这种错误需要管理员进行检查和修复。

3.4. KERN_ERR这个级别的错误消息表示系统出现了一般性的错误,但不会影响系统的正常工作。

这种错误通常需要记录下来,并在合适的时候进行检查和修复。

3.5. KERN_WARNING这个级别的消息表示系统出现了一些警告性的问题,但并不会影响系统的正常工作。

这种消息通常用于记录一些潜在的问题,以便后续的分析和调试。

3.6. KERN_NOTICE这个级别的消息表示系统出现了一些普通的通知信息。

这些信息通常用于记录系统的状态和运行情况,以便后续的分析和调试。

3.7. KERN_INFO这个级别的消息表示系统出现了一些普通的信息。

这些信息通常用于记录系统的状态和运行情况,以便后续的分析和调试。

3.8. KERN_DEBUG这个级别的消息表示系统出现了一些调试信息。

printk dict结构

printk dict结构

printk dict结构摘要:1.Printk 概述2.dict 结构介绍3.Printk 与dict 结构的关系4.使用Printk 打印dict 结构正文:1.Printk 概述Printk 是Linux 内核中的一个重要模块,主要用于打印内核中的调试信息。

它提供了一个方便的机制,让开发者能够在内核中插入调试语句,并在系统运行时输出相关信息,以帮助开发者调试和分析内核代码。

2.dict 结构介绍dict 结构是Python 中的一种数据结构,它是基于哈希表实现的一种键值对映射。

dict 结构可以用来存储具有唯一键的数据项,并能够通过键快速查找和访问对应的值。

在Python 中,字典是无序的,但可以通过一些方法对其进行排序。

3.Printk 与dict 结构的关系虽然Printk 和dict 结构分别属于Linux 内核和Python 编程语言,但它们之间存在一定的联系。

由于Printk 用于在内核中打印调试信息,而Python 中的dict 结构可以用来存储和查询数据,因此在某些场景下,开发者可能会使用Python 的dict 结构来解析和处理内核中的调试信息。

4.使用Printk 打印dict 结构在使用Printk 打印dict 结构时,需要先将dict 结构转换为适用于Printk 的格式。

这可以通过将dict 结构中的键值对转换为字符串,并按照特定的格式进行拼接来实现。

然后,将拼接后的字符串作为Printk 的参数进行打印。

在打印过程中,Printk 会根据字符串中的格式化字符串进行替换,并最终输出格式化后的字符串。

例如,假设有一个包含键值对的dict 结构:{"name": "Alice", "age": 30, "city": "Beijing"}。

Linux系统内核的性能优化研究

Linux系统内核的性能优化研究

Linux系统内核的性能优化研究Linux是一种开源的操作系统,因为其稳定性和可定制性而被广泛应用于服务器和嵌入式设备等领域。

Linux操作系统的灵活性是通过它的核心(内核)来实现的。

在Linux内核中,性能调优是一个重要的技术领域,它可以明显提高系统的吞吐量、响应时间和稳定性。

在本文中,我们将探讨Linux内核的性能优化研究。

一、代码调试技术调试是Linux内核性能优化的一个重要环节。

在编写代码时,因为错误的设计和代码缺陷等原因,程序可能会出现性能瓶颈。

为了调试这些问题,Linux开发者使用了多种技术,包括printf()语句和跟踪器。

printf()是C程序员熟悉的一种调试方法。

在Linux内核中,使用printk()函数取代printf()函数。

printk()函数可以输出相同的信息到内核日志缓冲区中。

内核日志存放在/var/log/kern.log和/var/log/syslog两个文件中。

跟踪器是另一种主要的调试技术,它可以使用trace-cmd和perf等工具进行操作。

跟踪器允许开发者监测系统的行为,分析和理解系统中的各个事件。

使用跟踪器可以帮助开发者发现问题并进行性能调优。

二、内存管理技术内存管理是Linux内核性能的另一个重要方面。

在Linux中,一个进程可以访问系统内存的一部分。

内存的管理是由一个复杂的层次结构组成的,其中主要的组成部分包括虚拟内存管理、物理内存管理和内存映射。

在Linux内核中,物理内存管理主要包括页面分配和页面回收。

页面分配通过页面伙伴系统(Page Buddy System)实现。

这个系统将物理内存分成多个大小相等的页面块,称为page frames。

在请求物理内存时,内核会使用这些page frames 来满足请求。

页面回收是为了保证物理内存的利用率。

在Linux中,可以通过两种回收机制实现:内存泄漏检查和大页回收。

内存泄漏检查技术基于一种称为Slab检查的机制,它会缓存共享数据结构,以减少分配和释放页面的次数。

Linuxprintk的日志级别和pr_debug

Linuxprintk的日志级别和pr_debug

Linuxprintk的⽇志级别和pr_debug1. 查看⽇志级别# cat /proc/sys/kernel/printk7417 四个数值分别表⽰。

控制台⽇志级别默认消息⽇志级别(未明确指定⽇志级别的消息)最⼩控制台⽇志级别默认控制台⽇志级别 ⽇志级别的定义在include/linux/kern_levels.h。

数值越⼩,级别越⾼。

当printk的⽇志级别⾼于控制台⽇志级别时,控制台打印⽇志。

#define KERN_EMERG KERN_SOH "0" /* system is unusable */#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */#define KERN_CRIT KERN_SOH "2" /* critical conditions */#define KERN_ERR KERN_SOH "3" /* error conditions */#define KERN_WARNING KERN_SOH "4" /* warning conditions */#define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */#define KERN_INFO KERN_SOH "6" /* informational */#define KERN_DEBUG KERN_SOH "7" /* debug-level messages */2. 控制台打印所有级别⽇志# echo8417 > /proc/sys/kernel/printk3. 查看所有级别⽇志 除了将⽇志打印在控制台,还可以通过dmesg命令查看所有级别⽇志。

理解printk函数【转】

理解printk函数【转】

理解printk函数【转】理解printk函数 Printk函数是在开发驱动过程中经常⽤到的⼀个函数,作⽤就是在串⼝上输出内核的信息。

这个常⽤的函数的执⾏过程未必⼤家都和清楚,下⾯的⽂章分析⼀下printk的执⾏过程,并说明printk函数的⼀些特点。

下⾯是printk的执⾏过程,重要的步骤有如下⼏个1. printk调⽤vprintk函数,⾸先是禁⽌抢占,并且关闭中断;2. 调⽤vscnprintf函数,将输出字符串按格式组织在printk_buf缓冲区域中;3. 调⽤emit_log_char函数,将printk_buf中的内容拷贝到log_buf中去;4. 调⽤release_console_sem函数将log_buf的内容发送到硬件上;根据上⾯列出来的printk的执⾏过程,我们需要了解到⼏个问题。

Printk执⾏过程是禁⽌抢占和关闭中断的,⽽从串⼝输出字符的速度⽐较缓慢,只导致printk会严重影响程序执⾏的速率。

然后printk函数中存在两个缓冲buf,⼀个buf叫做printk_buf,⼀个buf是log_buf。

Printk_buf只有1K,它的作⽤是临时按格式组织字符串的缓冲。

⽽log_buf是根据内核编译时来配置的,可以⼤道16K左右,是⼀个环形的缓冲。

在Linux系统中,⽤户态还可以通过/proc/ksmg将log_buf中的内容读出来。

/** Call the console drivers on a range of log_buf*/static void __call_console_drivers(unsigned start, unsigned end){struct console *con;for (con = console_drivers; con; con = con->next){if ((con->flags & CON_ENABLED) && con->write &&(cpu_online(smp_processor_id()) ||(con->flags & CON_ANYTIME)))con->write(con, &LOG_BUF(start), end - start);}}将log_buf中的内容向硬件上输出的时候,在console_drivers上⾯找到能⽤的console终端,然后调⽤write函数,将数据从硬件上输出去。

linux printk日志级别

linux printk日志级别

linux printk日志级别Linux 是一款广泛应用于服务器端和嵌入式系统的操作系统,它在可靠性和稳定性方面具有独特的优势。

日志是系统运行过程中记录和存储各种事件和信息的重要手段,Linux 内核提供了 printk 函数来输出系统日志。

printk 函数允许开发人员在代码中插入调试信息,并通过设置不同的日志级别来过滤输出,帮助开发人员调试和解决问题。

1. printk 函数使用printk 函数是 Linux 内核中用于输出日志信息的函数,它的原型定义如下:```int printk(const char *fmt, ...);```第一个参数 fmt 是一个格式化字符串,用于指定输出的格式,后续的可变参数用于填充该格式化字符串中的占位符。

printk 函数会将格式化的字符串输出到系统的控制台,也可以通过配置改变输出的目标。

在使用 printk 函数时,我们可以使用一些特殊的占位符来表示不同类型的参数。

例如,"%s" 表示字符串,"%d" 表示十进制整数,"%x" 表示十六进制整数等。

通过将相应类型的参数传递给 printk 函数,就可以将这些参数的值填充到格式化字符串中。

下面是一个示例,演示了如何使用 printk 函数输出一个字符串和一个整数:```printk("Hello, %s! The answer is %d.\n", "world", 42);```上述代码在系统日志中输出了一条消息:"Hello, world! The answeris 42."2. 日志级别为了更好地管理系统日志,Linux 内核定义了多个日志级别,开发人员可以根据需要选择合适的级别来输出日志信息。

根据重要性和紧急程度,Linux 提供了以下 8 个日志级别:- KERN_EMERG:用于严重错误消息,系统无法继续正常运行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

你知道Linux内核调试关键技术之一的printk?
1、简介(基于s3c2440 linux)
在内核调试技术之中,最简单的就是printk的使用了,它的用法和C语言应用程序中的printf使用类似,在应用程序中依靠的是stdio.h中的库,而在linux内核中没有这个库,所以在linux内核中,使用这个printk就要对内核的实现有一定的了解。

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

当printk(""......);中的n 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/printk7 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 "" /* 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。

相关文档
最新文档