printk无法打印信息

本文介绍了Linux内核中的printk函数,用于在内核模块中打印信息。printk根据日志级别决定是否将消息输出到控制台,其默认级别可能不会显示在终端上。通过指定日志级别或调整控制台日志级别,可以控制信息的显示。当klogd未运行时,日志信息可查看于/var/log/messages或/proc/kmsg。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自http://blog.chinaunix.net/uid-25811099-id-326899.html

 

对于做嵌入式或者熟悉linux内核的人来说,对printk这个函数一定不会感到陌生。printk相当于printf的孪生姐妹,她们一个运行在用户态,另一个则在内核态被人们所熟知。

  【原型】

  int printk(const char * fmt,…);

  【示例】

  与大多数展示printf的功能一样,我们也用一个helloworld的程序来演示printk的输出:

  编写一个内核模块:

  #include<linux/kernel.h>

  #include<linux/module.h>

  #if CONFIG_MODVERSIONS==1

  #define MODVERSIONS

  #include<linux/modversions.h>

  #endif

  MODULE_LICENSE("GPL");

  int init_module()

  {

  printk("hello.word-this is the kernel speaking\n");

  return 0;

  }

  void cleanup_module()

  {

  printk("Short is the life of a kernel module\n");

  }

  保存为文件hello.c

  编写一个Makefile:

  CC=gcc

  MODCFLAGS:=-O6 -Wall -DMODULE -D__KERNEL__ -DLINUX

  hello.o:hello.c /usr/include/linux/version.h

  $(CC) $(MODCFLAGS) -c hello.c

  echo insmod hello.o to turn it on

  保存为文件Makefile

  执行make

  我们可以看到生成了一个hello.o的内核模块,我们想通过这个模块在插入内核的时候输出

  "hello.word-this is the kernel speaking"

  这样一条信息。

  然后我们开始:

  [root@localhost root]# insmod hello.o

  [root@localhost root]#

  并没有输出任何消息。why?

  这也是printf和printk的一个不同的地方

  用printk,内核会根据日志级别,可能把消息打印到当前控制台上,这个控制台通常是一个字符模式的终端、一个串口打印机或是一个并口打印机。这些消息正常输出的前提是──日志输出级别小于console_loglevel(在内核中数字越小优先级越高)。

  没有指定日志级别的printk语句默认采用的级别是 DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上),其定义在linux26/kernel/printk.c中可以找到

  日志级别一共有8个级别,printk的日志级别定义如下(在include/linux/kernel.h中):

  #define KERN_EMERG    0

  #define KERN_ALERT     1

  #define KERN_CRIT       2

  #define KERN_ERR        3

  #define KERN_WARNING  4

  #define KERN_NOTICE    5

  #define KERN_INFO       6

  #define KERN_DEBUG     7

  现在我们来修改hello.c程序,使printk的输出级别为最高:

  printk("<0>""hello.word-this is the kernel speaking\n");

  然后重新编译hello.o,并插入内核:

  [root@localhost root]# insmod hello.o

  [root@localhost root]#

  Message from syslogd@localhost at Sat Aug 15 05:32:22 2009 ...

  localhost kernel: hello.word-this is the kernel speaking

  hello,world信息出现了。

  其实printk始终是能输出信息的,只不过不一定是到了终端上。我们可以去

  /var/log/messages这个文件里面去查看。

  如果klogd没有运行,消息不会传递到用户空间,只能查看/proc/kmsg

  通过读写/proc/sys/kernel/printk文件可读取和修改控制台的日志级别。查看这个文件的方法如下:

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

  上面显示的4个数据分别对应控制台日志级别、默认的消息日志级别、最低的控制台日志级别和默认的控制台日志级别。

  可用下面的命令设置当前日志级别:

  # echo 8 > /proc/sys/kernel/printk

  这样所有级别<8,(0-7)的消息都可以显示在控制台上. 

 

### Linux 内核中的 `printk` 函数 #### 功能概述 `printk` 是 Linux 内核中用于向控制台和其他日志目标发送消息的重要工具。这些消息可以来自内核的同部分,甚至是从内核深处发出的关键信息[^1]。 #### 使用机制 为了有条件地将数据传递给控制台设备,Linux 的 `printk` 利用了基于 `/proc` 文件系统的机制。通过查看特定的伪文件,用户空间程序能够配置 `printk` 行为: ```bash [root@ecs-3370 linux]# cat /proc/sys/kernel/printk 4 4 1 7 ``` 上述命令显示了当前系统上四个参数设置,它们分别代表默认级别、最低控制台日志级别、最低存储日志级别以及默认的消息前缀级别。 #### 参数解释 - **第一个数值 (default_message_loglevel)**:当模块或驱动未指定优先级时使用的默认值。 - **第二个数值 (minimum_console_level)**:低于此级别的消息打印到控制台上。 - **第三个数值 (default_console_loglevel)**:如果启动选项指定了 console,则使用该值作为初始控制台记录等级。 - **第四个数值 (console_loglevel)**:动态调整后的实际控制台输出级别。 #### 调试增强 对于希望启用更多调试信息的情况,可以通过内核参数来增加额外的日志输出。例如,在引导加载器命令行添加如下参数可实现这一目的: ```plaintext locktorture.verbose=[KNL] ``` 这会激活更多的 `printk()` 输出语句,有助于更深入地了解某些功能的工作情况[^2]。 #### 示例代码片段 下面是一个简单的 C 语言例子展示如何在内核模块里调用 `printk` 来生成同严重程度的信息: ```c #include <linux/module.h> #include <linux/kernel.h> static int __init my_module_init(void){ printk(KERN_INFO "Module loaded successfully\n"); return 0; } static void __exit my_module_exit(void){ printk(KERN_WARNING "Warning: Module is being unloaded!\n"); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); ``` 这段代码展示了两种同的日志级别——信息性和警告性,并说明了怎样利用宏定义 (`KERN_INFO`, `KERN_WARNING`) 来标注每条消息的重要性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值