自学内容网 自学内容网

【LINUX】pr_info函数开发摸索

1、打印开关可随时控制,开机如果要修改是否打印日志的话,需要修改代码重新编译内核才行,其实如果真要搞,应该有其他方法; 

2、打印次数,当前代码里边写的是1000次,其实可以根据传参动态修改打印日志次数,不过没有开发,只是大概展示了下;

3、函数未来可扩展;

运行效果:

linux_pr_info_self_哔哩哔哩_bilibililinux kernel 添加内核自定义日志后运行状态,代码地址:https://gitee.com/r77683962/linux-6.9.0内核版本6.9.0, 视频播放量 13、弹幕量 0、点赞数 0、投硬币枚数 0、收藏人数 0、转发人数 0, 视频作者 缘起性空aa, 作者简介 ,相关视频:2024版Linux内核源码分析(强烈推荐收藏!),三天让你学会Linux操作系统!,【网络安全】拜托三连了!这绝对是全B站最用心(没有之一)的Linux学习教程!,如何成为一名linux用户,B站强推!2024年最新Linux操作系统全套顶级天花板教程,血赚!学完即可上岸,拿走不谢!,【大佬秘籍】子牙老师告诉你,如何才能学会任何计算机技术,看懂任何代码:Java虚拟机、linux内核、redis、MySQL,【Linux虚拟机】wsl+ubuntu+vscode配置教程,请选择你的勾石操作系统,【操作系统】学起来,你就超过99%的人!保姆级教学,小白也可以轻松搞懂操作系统!,2024.6.22最新安卓【国际版抖音tiktok】iOS 免拔卡icon-default.png?t=N7T8https://www.bilibili.com/video/BV1Bi421Y7UP/?vd_source=0578c14da2b84f0964bbee439d4fd921

代码:

include/linux/printk_self.h · r77683962/linux-6.9.0 - Gitee.comicon-default.png?t=N7T8https://gitee.com/r77683962/linux-6.9.0/blob/70652d2129aae756fde3f9c440dd21177d9890cd/include/linux/printk_self.hinclude/linux/printk_self.h


#ifndef __KERNEL_PRINTK_SELF__
#define __KERNEL_PRINTK_SELF__

#include <linux/stdarg.h>
#include <linux/init.h>
#include <linux/kern_levels.h>
#include <linux/linkage.h>
#include <linux/ratelimit_types.h>
#include <linux/once_lite.h>

typedef enum 
{
PRINT_LOG_STATE_NONE = 0,
PRINT_LOG_STATE_LESS,
PRINT_LOG_STATE_DEFAULT,
PRINT_LOG_STATE_MORE,
PRINT_LOG_STATE_TIMES
}PRINT_LOG_STATE_EN;

extern int iGlobalLogPrintLevel;
extern int iGlobalLogPrintTimes; 


void  GlobalLogPrintTimesSet(unsigned int  value);


void  GlobalLogPrintLevelSet(int value);

/**
 * pr_info - Print an info-level message
 * @fmt: format string
 * @...: arguments for the format string
 *
 * This macro expands to a printk with KERN_INFO loglevel. It uses pr_fmt() to
 * generate the format string.
 */
#define pr_info_self(fmt, ...) \
({                                                                      \
if (iGlobalLogPrintLevel == PRINT_LOG_STATE_DEFAULT) \
    printk(KERN_INFO "[%s %s %d DEFAULT] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
else if (iGlobalLogPrintLevel == PRINT_LOG_STATE_LESS) \
    printk(KERN_INFO "[LESS] "pr_fmt(fmt), ##__VA_ARGS__); \
else if (iGlobalLogPrintLevel == PRINT_LOG_STATE_MORE) \
    printk(KERN_INFO "[%s %s %d MORE] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
else if (iGlobalLogPrintLevel == PRINT_LOG_STATE_TIMES && iGlobalLogPrintTimes > 0) \
{  \
    printk(KERN_INFO "[%s %s %d TIMES: %d ] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, iGlobalLogPrintTimes, ##__VA_ARGS__); \
    iGlobalLogPrintTimes--; \
} \
})


#endif

这个枚举是可以扩展的,比如自己想添加其他类型的打印类型,像java log打印就比较复杂;

另外就是pr_info_self这里也可以扩展,不过这里的语法比较复杂,什么斜杠,fmt,双引号什么的,修改代码的时候要注意

kernel/printk/printk_self.c · r77683962/linux-6.9.0 - Gitee.comicon-default.png?t=N7T8https://gitee.com/r77683962/linux-6.9.0/blob/master/kernel/printk/printk_self.c

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/stdarg.h>
#include <linux/init.h>
#include <linux/kern_levels.h>
#include <linux/linkage.h>
#include <linux/ratelimit_types.h>
#include <linux/once_lite.h>

#include <linux/printk_self.h>


int iGlobalLogPrintLevel;
EXPORT_SYMBOL(iGlobalLogPrintLevel);

int iGlobalLogPrintTimes; 
EXPORT_SYMBOL(iGlobalLogPrintTimes);


void  GlobalLogPrintTimesSet(unsigned int  value)
{
iGlobalLogPrintTimes = value;
}
EXPORT_SYMBOL(GlobalLogPrintTimesSet);

void  GlobalLogPrintLevelSet(int value)
{
iGlobalLogPrintLevel = value;
}
EXPORT_SYMBOL(GlobalLogPrintLevelSet);



这就是实现的一点点封装,类似面向对象编译的类。

这里要注意export_symbol这个宏不能少。

不然编译不会有问题,链接会报错。 

fs/open.c · r77683962/linux-6.9.0 - Gitee.comicon-default.png?t=N7T8https://gitee.com/r77683962/linux-6.9.0/blob/70652d2129aae756fde3f9c440dd21177d9890cd/fs/open.c

static long do_sys_openat2(int dfd, const char __user *filename,
   struct open_how *how)
{
struct open_flags op;
int fd = build_open_flags(how, &op);
struct filename *tmp;
pr_info_self("");

if (fd)
return fd;


tmp = getname(filename);
if (IS_ERR(tmp))
return PTR_ERR(tmp);

if (strncmp_self(tmp->name, "log_none", 8) == 0)
{
GlobalLogPrintLevelSet(PRINT_LOG_STATE_NONE);
pr_info_self("log_none filename: %s", tmp->name);
}
else if (strncmp_self(tmp->name, "log_less", 8) == 0)
{
GlobalLogPrintLevelSet(PRINT_LOG_STATE_LESS);
pr_info_self("log_less filename: %s", tmp->name);
}
else if (strncmp_self(tmp->name, "log_default", 11) == 0)
{
GlobalLogPrintLevelSet(PRINT_LOG_STATE_DEFAULT);
pr_info_self("log_default filename: %s", tmp->name);
}
else if (strncmp_self(tmp->name, "log_more", 8) == 0)
{
GlobalLogPrintLevelSet(PRINT_LOG_STATE_MORE);
pr_info_self("log_more filename: %s", tmp->name);
}
else if (strncmp_self(tmp->name, "log_times", 9) == 0)
{
GlobalLogPrintTimesSet(1000);
GlobalLogPrintLevelSet(PRINT_LOG_STATE_TIMES);
pr_info_self("log_times filename: %s", tmp->name);
}

fd = get_unused_fd_flags(how->flags);
if (fd >= 0) {
struct file *f = do_filp_open(dfd, tmp, &op);
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
fd_install(fd, f);
}
}
putname(tmp);
return fd;
}

这里边就是根据文件名(其实视频里边操作的都是创建文件的文件名),来修改内核日志打印的状态。

初始化:

include/linux/printk.h · r77683962/linux-6.9.0 - Gitee.comicon-default.png?t=N7T8https://gitee.com/r77683962/linux-6.9.0/blob/master/include/linux/printk.h如果想让内核在起动的时候就打开,需要修改iGlobalLogPrintLevel = PRINT_LOG_STATE_NONE;

static inline void setup_log_buf(int early)
{
iGlobalLogPrintLevel = PRINT_LOG_STATE_NONE;
iGlobalLogPrintTimes = 0; 

}

这就是变量初始化。 

kernel/printk/Makefile · r77683962/linux-6.9.0 - Gitee.comicon-default.png?t=N7T8https://gitee.com/r77683962/linux-6.9.0/blob/master/kernel/printk/Makefile

# SPDX-License-Identifier: GPL-2.0-only
obj-y= printk.o printk_self.o
obj-$(CONFIG_PRINTK)+= printk_safe.o nbcon.o
obj-$(CONFIG_A11Y_BRAILLE_CONSOLE)+= braille.o
obj-$(CONFIG_PRINTK_INDEX)+= index.o

obj-$(CONFIG_PRINTK)                 += printk_support.o
printk_support-y             := printk_ringbuffer.o
printk_support-$(CONFIG_SYSCTL)     += sysctl.o

这就是Makefile的第一行,因为我们新增了两个文件,要新生成对应的.o文件 

代码比较简单。


原文地址:https://blog.csdn.net/r77683962/article/details/139896552

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!