printk函数 相关

  • printk简介
    内核源码中用来记录日志信息的函数,只能在内核源码范围内使用。用法和printf非常相似

  • printf 和 printk 对比
    printf:glibc实现的打印函数,工作于用户空间
    printk:内核模块无法使用glibc库函数,内核自身实现的一个类printf函数,但是需要指定打印等级(若不指定就是用默认的打印等级)。

  • printk函数使用
    在使用printk时我们会将 打印等级/日志级别 放到最开始的位置,如
    printk(KERN_EMERG "EMERG\n");
    我们没有设置日志级别时,会为他设一个默认的日志级别:default_message_loglevel。
    只有当 printk() 中的消息日志级别小于当前控制台日志级别(console_printk[0])时,printk 的信息就会在控制台上显示。

  • printk打印等级相关定义如下

// include/linux/kern_levels.h
#define KERN_SOH    	"\001"      	/* ASCII Start Of Header */
...
#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 */

  • 查看当前系统printk打印等级:cat /proc/sys/kernel/printk (不手动去修改的话就是依次打印源码中这四个数组成员的值)
    只有 prink 指定的打印等级比 console 小 才能打印到console,等于都不行。
//kernel/printk/printk.c
int console_printk[4] = {
    CONSOLE_LOGLEVEL_DEFAULT,   /* console_loglevel 当前控制台日志级别*/
    MESSAGE_LOGLEVEL_DEFAULT,   /* default_message_loglevel 默认消息日志级别*/
    CONSOLE_LOGLEVEL_MIN,       /* minimum_console_loglevel 最小的控制台级别*/
    CONSOLE_LOGLEVEL_DEFAULT,   /* default_console_loglevel 默认控制台日志级别*/
};

/ # 
/ # 
/ # 
/ # cat /proc/sys/kernel/printk
7       4       1       7
/ # 
/ # 
/ # 
  • 若要修改上述默认优先级设置:
    1、修改源码
    2、修改/proc/sys/kernel/printk文件
    将要设置的值写入到/proc/sys/kernel/printk中。我们要先cat /proc/sys/kernel/printk来看一下这个文件中都有什么值。然后我们再写入。其中这里的格式为:控制台的日志级别、默认消息日志级别、最小控制台日志级别和默认控制台日志级别。而我们要设置的就是第一个控制台的日志级别。我们通过echo “W X Y Z” > /proc/sys/kernel/printk 将我们想要设置的四个值写入到/proc/sys/kernel/printk中。

通过 dmesg 可以查看 printk 的所有打印信息

  • 内核log缓冲区大小有限制,缓冲区数据可能被冲掉

  • 例程

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

// __init 是把该函数放到统一的段里,所有内核模块的入口函数都存到这个指定的段里,
// 等到内核调用了就释放这个段,一次节约内存空间
// __exit 同理
static int __init hello_init(void)
{
	printk(KERN_EMERG"%s(%d):[KERN_EMERG]\r\n", __FILE__, __LINE__);
	// 也可以手动替换上面的宏如下,效果是一样的
	// printk("\001" "1""[ KERN_EMERG ]  Hello World Module Init\n");
    printk("\001" "7""%s(%d):[\"<7>\"]\r\n", __FILE__, __LINE__);
    printk("\001" "6""%s(%d):[\"<7>\"]\r\n", __FILE__, __LINE__);
    printk(KERN_DEBUG"\n\n%s(%d):[\"<7>\"]\r\n", __FILE__, __LINE__);
	return 0;
}

static void __exit hello_exit(void)
{
	printk("[ default ]   goodbye\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("author");
MODULE_DESCRIPTION("hello world module");
MODULE_ALIAS("test_module");
  • 编译测试
/ # 
/ # 
/ # 
/ # cat /proc/sys/kernel/printk
7       4       1       7
/ # 
/ # 
/ # modprobe test.ko
/home/jl/linux/imx6ull/linux_driver/z_exercise/test.c(10):[KERN_EMERG]
/home/jl/linux/imx6ull/linux_driver/z_exercise/test.c(14):["<7>"]
/ # 
/ # 
/ # 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值