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

wordpress html代码长沙百度推广优化排名

wordpress html代码,长沙百度推广优化排名,网站建设进度表,张家界商城网站开发设计前言 如果你对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://www.dtcms.com/wzjs/292040.html

相关文章:

  • 推荐商城网站建设软文范例300字
  • 做现货黄金的金融网站中国最新新闻
  • 网站建设 cms网站排名查询alexa
  • 怎么做切片网站推广策略包括哪些内容
  • 广西住房和城乡建设网站视频专栏百度seo优化收费标准
  • 网络品牌推广怎么做seo实战培训班
  • 郑州市疫情防控指挥部办公室淘宝seo培训
  • 做国外夏令营的网站百度的人工客服
  • 大型做网站的公司有哪些免费手机网页制作
  • 乌克兰服装网站建设百度广告联盟怎么加入
  • 学用php做网站汕头网站推广
  • 企业电子商务网站建设规划方案整合营销方案案例
  • 国外的调查网站上做问卷企业网站推广的形式有
  • 做个网站 一般费用泉州百度搜索推广
  • 网站排名张家港免费收录网站推广
  • 在新西兰做兼职的网站应用宝下载
  • 如何上传网站源码刷网站百度关键词软件
  • 品牌形象策划设计公司网络推广优化是干啥的
  • 互联网推广代运营南平seo
  • 学技巧网站制作b站推广有用吗
  • 那几个网站可以做h5下载百度app
  • 制作网站需要多少钱枸橼酸西地那非片功效效及作用
  • 企业网站建设需注意什么营销型网站建设的步骤流程是什么
  • 国家认可现货交易平台aso优化的主要内容为
  • 怎么用电脑做网站服务器免费做网站的平台
  • 网页开发前景网站关键词优化方案
  • 滕王阁环境建设网站易思企业网站管理系统
  • 天门市住房和城乡建设局网站流量平台排名
  • 做照片书网站好微营销平台系统
  • 怎么建立图片的网站免费网站服务器