当前位置: 首页 > wzjs >正文

苏州公司网站建设报价华文细黑做网站有版权吗

苏州公司网站建设报价,华文细黑做网站有版权吗,正能量网站免费入口有限公司,ppt 模板免费下载前言 如果你对printk的基本用法还不熟悉,请先阅读: Linux Kernel调试:强大的printk(一) 上一篇Linux Kernel调试:强大的printk(一)我们介绍了printk的基础知识和基本用法&#xf…

前言

如果你对printk的基本用法还不熟悉,请先阅读:

Linux Kernel调试:强大的printk(一)

上一篇Linux Kernel调试:强大的printk(一)我们介绍了printk的基础知识和基本用法,了解了printk的一些特性,比如支持输出级别等,不过这是最基础的用法,在实际项目中,一般不会直接这样用,本篇就来讲一下printk的进阶用法。

如果对pr_xxx已经熟悉了,可以直接阅读后面的内容:

Linux Kernel调试:强大的printk(三):dev_xxx相关的内容,以及限制打印速率

pr_xxx

使用printk需要指定日志级别,虽然也可以不指定级别(使用默认级别),但是在实际使用中还是推荐每次调用都最好指定级别,不过这样一来就很麻烦,且不够清晰,所以内核在include/linux/printk.h中提供了如下形式的定义:

#define pr_emerg(fmt, ...) \printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)#define pr_alert(fmt, ...) \printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)#define pr_crit(fmt, ...) \printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)#define pr_err(fmt, ...) \printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)#define pr_warn(fmt, ...) \printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)#define pr_notice(fmt, ...) \printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)#define pr_info(fmt, ...) \printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)#define pr_cont(fmt, ...) \printk(KERN_CONT fmt, ##__VA_ARGS__)// 这里是从源码中精简出来的
#define pr_debug(fmt, ...) \printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)

由这些定义也可以看出,pr_xxx对应于printk的不同级别,例如pr_emerg就等价于KERN_EMERG级别的printk,这样我们在内核编程时,或者写内核模块时,就可以直接使用pr_xxx来输出log了,也是推荐使用这种方式。

我们把上一篇Linux Kernel调试:强大的printk(一)的示例代码替换成pr_xxx即可进行实验,效果和上一篇一样,这里不在赘述。

这里着重讲一下上面代码中的pr_fmt,这是一个宏,默认定义也位于include/linux/printk.h

/*** pr_fmt - used by the pr_*() macros to generate the printk format string* @fmt: format string passed from a pr_*() macro** This macro can be used to generate a unified format string for pr_*()* macros. A common use is to prefix all pr_*() messages in a file with a common* string. For example, defining this at the top of a source file:**        #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt** would prefix all pr_info, pr_emerg... messages in the file with the module* name.*/
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif

这个宏的作用就是为我们要打印的信息生成统一的格式字符串。从上面的默认定义也可以看出,如果之前没有定义pr_fmt那就将pr_fmt(fmt)定义为fmt,所以如果我们要使用pr_fmt来统一打印的格式,就需要在包含include/linux/printk.h之前定义pr_fmt,下面我们通过示例代码来演示pr_fmt宏的作用,可到这里获取https://gitee.com/coolloser/linux-kerenl-debug

// 定义模块的格式化字符串
#define pr_fmt(fmt) "%s:%s():%d: " fmt, KBUILD_MODNAME, __func__, __LINE__#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>// 定义模块加载函数
static int __init pr_fmt_init(void)
{pr_info("====printk模块加载成功!====\n");pr_debug("这是一个DEBUG级别的信息\n");pr_info("这是一个INFO级别的信息\n");pr_warn("这是一个WARNING级别的信息\n");pr_err("这是一个ERROR级别的信息\n");pr_crit("这是一个CRITICAL级别的信息\n");pr_alert("这是一个ALERT级别的信息\n");pr_emerg("这是一个EMERGENCY级别的信息\n");// 使用KERN_CONT继续上一条日志消息pr_info("这是一条需要继续的信息...");pr_cont("...这是继续的部分\n");return 0; // 返回0表示模块加载成功
}// 定义模块卸载函数
static void __exit pr_fmt_exit(void)
{pr_info("====printk模块卸载成功!====\n");
}// 注册模块加载和卸载函数
module_init(pr_fmt_init);
module_exit(pr_fmt_exit);// 模块信息
MODULE_LICENSE("GPL");
MODULE_AUTHOR("your_name");
MODULE_DESCRIPTION("pr_fmt内核模块示例");
MODULE_VERSION("0.1");
# 定义模块名称
MODULE_NAME := pr_fmt# 定义内核构建目录,替换成你自己的路径
KERNEL_BUILD_DIR := /home/leo/debug_kernel/linux-6.12.28# 定义目标文件
obj-m += $(MODULE_NAME).o# 默认目标
all:@echo "Building the $(MODULE_NAME) kernel module..."$(MAKE) -C $(KERNEL_BUILD_DIR) M=$(PWD) modules# 清理目标
clean:@echo "Cleaning up the build environment..."$(MAKE) -C $(KERNEL_BUILD_DIR) M=$(PWD) clean

执行make进行编译,然后执行sudo insmod pr_fmt.ko加载模块,之后执行dmesg查看log信息:

可以看到,在每一条log之前都加入了[模块名称]:[函数名]:[行号]

所以使用pr_fmt,一处定义,多处使用,我们就可以很方便的添加我们需要的信息了,这里还是要再提醒一下,定义pr_fmt一定要在包含include/linux/printk.h之前,或者在模块源码文件的最开始定义。

pr_debug和pr_devel

在内核源码中,pr_debug和pr_devel的定义和其他几个pr_xxx不同:

pr_debug的定义如下:

/* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_DEBUG) || \(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#include <linux/dynamic_debug.h>/*** pr_debug - Print a debug-level message conditionally* @fmt: format string* @...: arguments for the format string** This macro expands to dynamic_pr_debug() if CONFIG_DYNAMIC_DEBUG is* set. Otherwise, if DEBUG is defined, it's equivalent to a printk with* KERN_DEBUG loglevel. If DEBUG is not defined it does nothing.** It uses pr_fmt() to generate the format string (dynamic_pr_debug() uses* pr_fmt() internally).*/
#define pr_debug(fmt, ...)                        \dynamic_pr_debug(fmt, ##__VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...) \no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

可以看到,如果配置了动态debug则pr_debug定义为了dynamic_pr_debug(关于动态打印以后会单独介绍),如果定义了DEBUG则pr_debug定义为了KERN_DEBUG级别的printk,否则pr_debug就是no_printk

pr_devel定义如下:

/*** pr_devel - Print a debug-level message conditionally* @fmt: format string* @...: arguments for the format string** This macro expands to a printk with KERN_DEBUG loglevel if DEBUG is* defined. Otherwise it does nothing.** It uses pr_fmt() to generate the format string.*/
#ifdef DEBUG
#define pr_devel(fmt, ...) \printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_devel(fmt, ...) \no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

可以看到如果定义了DEBUG,pr_devel和pr_debug一样也是KERN_DEBUG级别的printk,否则也是no_printk

所以我们如果要打印debug信息优先使用pr_debug,尽量不要使用pr_devel,因为pr_debug可以使用动态打印,pr_devel则没有使用动态打印,一旦我们不处于debug模式,就没法再查看对应log了。

pr_debug的打印去哪了

不知道你有没有发现,我们上面的示例代码中明明有:

pr_debug("这是一个DEBUG级别的信息\n");

但是在运行结果中,却没有这句打印:

那pr_debug的打印去哪了?其实从pr_debug的定义中我们也能发现问题,因为我们编译内核模块时没有定义DEBUG宏,所以pr_debug现在是no_printk,自然就没有打印出来了,下面我们修改Makefile使编译选项定义DEBUG宏,注意其中的ccflags-y += -DDEBUG

# 定义模块名称
MODULE_NAME := pr_fmt# 定义内核构建目录,替换成你自己的路径
KERNEL_BUILD_DIR := /home/leo/debug_kernel/linux-6.12.28# 定义目标文件
obj-m += $(MODULE_NAME).occflags-y += -DDEBUG# 默认目标
all:@echo "Building the $(MODULE_NAME) kernel module..."$(MAKE) -C $(KERNEL_BUILD_DIR) M=$(PWD) modules# 清理目标
clean:@echo "Cleaning up the build environment..."$(MAKE) -C $(KERNEL_BUILD_DIR) M=$(PWD) clean

现在再编译加载模块,执行dmesg查看:

终于打印出来了^_^

其实,代码中,在包含include/linux/printk.h之前通过#define DEBUG也可以让pr_debug打印出来,这里不再演示,需要你自己动手~

总结

本文重点介绍了pr_xxx的特点以及用法,pr_xxx是对printk的包装,但是其含义更加明确,使用更加方便,所以我们在实际开发中,优先使用pr_xxx进行log输出,还需要特别注意的是pr_debug,这个在我们开发阶段很有用处,且在后面我们介绍的动态打印中也有很大的用处

下一篇我们介绍dev_xxx:

Linux Kernel调试:强大的printk(三)


文章转载自:

http://wyibWJ7j.gbfck.cn
http://3bzXXjBT.gbfck.cn
http://lr7Qp2vS.gbfck.cn
http://8uN78JrM.gbfck.cn
http://drNzCgdA.gbfck.cn
http://NDCFp5zc.gbfck.cn
http://aKhZBDdc.gbfck.cn
http://CMDf2mTi.gbfck.cn
http://xUxQbx8J.gbfck.cn
http://9pXeaMLx.gbfck.cn
http://3EoapeVO.gbfck.cn
http://ERRXpzvk.gbfck.cn
http://KljjtQ2e.gbfck.cn
http://FDK74ChD.gbfck.cn
http://9hHNRUuy.gbfck.cn
http://AZXMi7dI.gbfck.cn
http://Jwhtvwsv.gbfck.cn
http://uAppfw6B.gbfck.cn
http://XmXvqjfN.gbfck.cn
http://9L48hu5W.gbfck.cn
http://gVtWnuYL.gbfck.cn
http://0Hw1L0pn.gbfck.cn
http://3ppEnwYP.gbfck.cn
http://485eK0Cq.gbfck.cn
http://0MAOEhED.gbfck.cn
http://hyP4yGlD.gbfck.cn
http://atOj9OBW.gbfck.cn
http://N9GA8X6u.gbfck.cn
http://GgCnURqS.gbfck.cn
http://pSTHnajC.gbfck.cn
http://www.dtcms.com/wzjs/716078.html

相关文章:

  • 手机网站生成app网站管理平台模板
  • 网站开发难题wordpress最好的编辑器下载
  • wordpress建站Pdf易语言跳到指定网站怎么做
  • 如何制作ppt视频教程网站优化工作内容
  • 湖北强涛建设工程有限公司网站邻水网站建设
  • 小语种网站开发同城推广
  • 怎么制作一个表白网站网站后台改网页底色
  • 怎么用ps做网站首页图片尺寸网站建设和维护合同
  • 网站开发流程详细介绍南阳住房和城乡建设厅网站
  • 非织梦做的网站能仿吗装修公司网站设计
  • 淄博网站建设给力臻动传媒广州建站模板
  • 专业的郑州网站推广成都网站制作东三环
  • 网站开发的总结与展望广告公司手机网站建设
  • 响应式网站模板的特点模版网站开发
  • 做网站那个好海口免费自助建站模板
  • 即墨网站建设在哪优化网站标题和描述的方法
  • 做网站需要什么认证徐州祥云做网站
  • 制作公司网站设建筑企业网站源码
  • 百度站长平台有哪些功能虚拟货币网站建设
  • 上海网站快速排名wordpress科技主题公园
  • 做报名表的网站中国建设银行积分查询网站
  • 制作网站的模板下载软件在茂名哪里可以做网站
  • 邓卅做网站在什么地方郑州整站关键词搜索排名技术
  • 门户网站模板html5简述网站开发工作流程
  • 货代可以从哪些网站开发客户给别人做网站必须有icp
  • 网站开发 太原网络整合营销
  • 建设网站怎样分配给用户空间做采购应该关注的网站
  • 百容千域可以免费做网站吗网站建设单子
  • wordpress 主题开发上海网站关键词优化
  • 在唐山做网站多少钱河南郑州最新消息