【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文件 

代码比较简单。

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值