Linux内核打印函数printk

2023-12-20 13:55:48

一.? 简介

在 Linux系统下,有用户空间与内核空间的区分。

应用程序运行在用户空间,而 Linux 驱动属于内核的一部分,因此驱动运行于内核空间。

应用程序需要打印信息到串口时,一般调用 printf()函数,但是,内核中需要打印信息时则会调用 printk()函数。

本文简单学习 printk()函数的使用。

二.? Linux内核打印-printk函数

1. printk()函数的打印级别

Linux 内核中没有 printf 这个函数。printk 相当于 printf 的孪生兄妹,printf() 函数运行在用户态,printk()函数运行在内核态。在内核中想要向控制台输出或显示一些内容,必须使用 printk() 函数。不同之处在于,printk 可以根据日志级别对消息进行分类,一共有 8 个消息级别。

8 个消息级别定义在文件 include/linux/kern_levels.h 里面,定义如下:

#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()函数打印一共定义了 8 个级别,其中 0 的优先级最高, 7 的优先级最低。如果要设置消息级别,参 考如下示例:
printk(KERN_EMERG "gsmi: Log Shutdown Reason\n");

2.?? 默认打印级别

如果使printk 的 时 候 不 显 式 的 设 置 消 息 级 别 , 那 么 printk 将 会 采 用 默 认 级 别

MESSAGE_LOGLEVEL_DEFAULT MESSAGE_LOGLEVEL_DEFAULT 默认为 4 include/linux/printk.h 中有个宏 CONSOLE_LOGLEVEL_DEFAULT ,定义如下:
#define CONSOLE_LOGLEVEL_DEFAULT 7
CONSOLE_LOGLEVEL_DEFAULT 控制着哪些级别的消息可以显示在控制台上,此宏默认 7 ,意味着只有优先级高于 7 的消息才能显示在控制台上。
默认消息级别为 4,4 的级别比 7 高,所示直接使用 printk 输出的信息是可以显示在控制台上的。

注意: 这个就是 printk 和 printf 的最大区别,可以通过消息级别来决定哪些消息可以显示在控制
台上!

三.? 举例

例如,可以在 前面编写的字符驱动模块框架代码中,添加 printk()打印。chrdevbase.c 添加后如下:

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

/*
*  驱动模块入口函数
*/
static int __init chrdevbase_init(void)
{
    printk("chrdevbase_init()!\n\r");
	return 0;
}

/*
*  驱动模块出口函数
*/
static void __exit chrdevbase_exit(void)
{
    printk("chrdevbase_exit()!\r\n");
}

/*
* 驱动模块的入口与出口函数
*/
module_init(chrdevbase_init); /* 入口 */
module_exit(chrdevbase_exit); /* 出口 */


MODULE_LICENSE("GPL");
MODULE_AUTHOR("LingXueWu");

首先,重新编译 工程,会生成 .ko文件。将 .ko 文件拷贝到 开发板根文件系统 /lib/modules/4.1.15目录下:

其次,开发板上电后,会进入开发板根文件系统,输入 "cd /lib/modules/4.1.15" 命令,进入 /lib/modules/4.1.15目录:

/ # cd lib/modules/4.1.15/
/lib/modules/4.1.15 # ls
chrdevbase.ko    modules.alias    modules.dep      modules.symbols

最后,挂载驱动模块:

/lib/modules/4.1.15 # modprobe chrdevbase.ko 
chrdevbase_init()!
/lib/modules/4.1.15 # 

可以看出,当使用 modprobe 命令挂载驱动模块时,是调用了 chrdevbase_init()函数。

输入 "lsmod" 命令,查看驱动模块:

/lib/modules/4.1.15 # lsmod 
Module                  Size  Used by    Tainted: G  
chrdevbase               680  0 
/lib/modules/4.1.15 # 

卸载驱动模块:

/lib/modules/4.1.15 # rmmod chrdevbase.ko 

chrdevbase_exit()!
/lib/modules/4.1.15 # 

可以看出,当卸载驱动模块时,是运行了 chrdevbase_exit()函数。

文章来源:https://blog.csdn.net/wojiaxiaohuang2014/article/details/135104778
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。