【LINUX】pr_info函数开发摸索

news2024/9/20 7:55:19

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

代码比较简单。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1939486.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CUDA编程00 - 配置CUDA开发环境

第一步&#xff1a; 在一台装有Nvidia显卡和驱动的机器上&#xff0c;用nvidia-smi命令查看显卡所支持cuda版本 第二步&#xff1a; 到Nvidia官网下载CUDA Toolkit并安装&#xff0c;CUDA Toolkit Archive | NVIDIA Developer 安装时按提示下一步即可&#xff0c;安装完成用 …

Django cursor()增删改查和shell环境执行脚本

在Django中&#xff0c;cursor()方法是DatabaseWrapper对象&#xff08;由django.db.connectio提供&#xff09;的一个方法&#xff0c;用于创建一个游标对象。这个游标对象可以用来执行SQL命令&#xff0c;从而实现对数据库的增删改查操作。 查询&#xff08;Select&#xff0…

C++初学者指南-5.标准库(第一部分)--标准库查询存在算法

C初学者指南-5.标准库(第一部分)–标准库查询存在算法 文章目录 C初学者指南-5.标准库(第一部分)--标准库查询存在算法any_of / all_of / none_ofcountcount_if相关内容 不熟悉 C 的标准库算法&#xff1f; ⇒ 简介 any_of / all_of / none_of 如果在输入范围(所有元素…

2024最新教程,在docker中安装kali,并配置ssh连接

docker的基本使用&#xff1a;搭建高效攻防靶场vulfocus与Docker仓库管理实战&#xff1a;从听说到入门 拉取kali官方镜像 docker pull kalilinux/kali-rolling 启动一个kali镜像&#xff0c;将容器中的22端口映射到主机100端口&#xff0c;方便ssh直接连接 docker run -it…

Unity UGUI 之 Toggle

​本文仅作学习笔记与交流&#xff0c;不作任何商业用途本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正​ 1.什么是Toggle&#xff1f; Unity - Manual: Toggle 带复选框的开关&#xff0c;可…

linux-二元信号量和计数信号量-生产者消费者模型以及用二元信号量实现-死锁(2)-侠义消息队列(fifo)-proc文件系统

二元信号量和计数信号量的区别&#xff1a; 二元信号量和计数信号量在嵌入式系统和多任务环境中都是重要的同步机制&#xff0c;用于控制对共享资源的访问。它们之间的主要区别体现在以下几个方面&#xff1a; 1. 状态表示 二元信号量&#xff08;Binary Semaphore&#xff09;…

[计算机基础]一、计算机组成原理

计算机组成原理的考察目标为&#xff1a; 1. 掌握单处理器计算机系统中主要部件的工作原理、组成结构以及相互连接方式。 2. 掌握指令集体系结构的基本知识和基本实现方法&#xff0c;对计算机硬件相关问题进行分析&#xff0c;并能够对相关部件进行设计。 3. 理解计算机系统的…

HTML5-canvas1

1、canvas&#xff1a;创建画布 <canvas id"canvas"></canvas>2、画一条直线 var canvasdocument.getElementById(cancas&#xff09;; canvas.width800; canvas.height800; var contextcanvas.getContext(2d); //获得2d绘图上下文环境 //画一条直线 c…

算法 - 图论Dijkstra(原理、思路代码实现、以东南大学真题为例讲解手算方法)

Dijkstra 算法原理&#xff1a; Dijkstra算法是一种经典的用于计算单源最短路径的算法。它可以在带权重的图中找到从源节点到所有其他节点的最短路径。Dijkstra算法通过贪心策略&#xff0c;不断选择当前已知最短路径最小的节点&#xff0c;更新其邻接节点的路径长度&#xff…

Linux之旅:常用的指令,热键和权限管理

目录 前言 1. Linux指令 &#xff08;1&#xff09; ls &#xff08;2&#xff09; pwd 和 cd &#xff08;3&#xff09;touch 和 mkdir &#xff08;4&#xff09; rmdir 和 rm &#xff08;5&#xff09;cp &#xff08;6&#xff09;mv &#xff08;7&#xff09;…

Qt窗口介绍

Qt窗口 一、Qt窗口二、菜单栏创建菜单栏在菜单栏中添加菜单创建菜单项在菜单项之间添加分割线综合练习 三、工具栏创建工具栏设置停靠位置设置浮动属性设置移动属性综合练习 四、状态栏状态栏的创建在状态栏中显示实时消息在状态栏显示永久的消息 五、浮动窗口浮动窗口的创建设…

达梦数据库系列—29. DTS迁移ORACLE到DM

目录 1.ORACLE源端信息 2.DM目的端信息 3.DTS 迁移评估 4.数据库迁移 4.1 Oracle 源端数据库准备 4.2 目的端达梦数据库准备 初始化参数设置 兼容性参数设置 表空间规划 用户规划 创建迁移用户和表空间 4.3迁移步骤 创建迁移 配置数据源 配置迁移对象及策略 开…

Vue3 --- 路由

路由就是一组key-value的对应关系&#xff1b;多个路由&#xff0c;需要经过路由器的管理。 1. 基本切换效果 安装路由器 npm i vue-router /router/index.ts // import { createRouter, createWebHistory } from vue-router import Home from /components/Home.vue import…

[Armbian] 部署Docker版Home Assistent,安装HACS并连接米家设备

title: [Armbian] 部署Docker版Home Assistent&#xff0c;安装HACS并连接米家设备 date: 2024-07-21T10:51:23Z lastmod: 2024-07-21T11:40:39Z [Armbian] 部署Docker版Home Assistent&#xff0c;安装HACS并连接米家设备 官网&#xff1a;Home Assistant (home-assistant.i…

算法——滑动窗口(day6)

1004.最大连续1的个数 ||| 1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 这道题如果能转化为滑动窗口的话就会很简单&#xff0c;因为我们如果尝试去把0翻转为1再计数的话等到第2轮又得重新翻转回来&#xff0c;费时费力~ 那么我…

gihub导入gitee仓库实现仓库同步

昨天在GitHub里导入了gitee仓库&#xff0c;但是在仓库同步这里卡了很久&#xff0c;因为网上大多数都是从github导入gitee&#xff0c;然后github生成token放入实现同步&#xff0c;但是我找到一种更为方便的&#xff01; 1.首先找到项目文件下的.git文件里的config文件 2.在…

linux 下将文件安装的mysql.server服务添加到systemctl中管理

1、找到mysql 的 mysql.server/ 文件位置 find / -name mysql.server 2、编辑mysql.server脚本&#xff0c;并将mysql.server脚本添加到linux服务 3、将mysql.server 复制到etc/init.d/mysqld 目录 cp /app/db/mysql/support-files/mysql.server /etc/init.d/mysqld 4、授权…

08 B端产品业务调研的流程(1)

业务调研是掌握业务情况的有效方法。一般核心流程如下图&#xff1a; 明确调研目标&#xff1a;即调研的目标&#xff0c;解决为什么要做业务调研&#xff0c;期望解决什么问题&#xff0c;达到什么样效果&#xff0c;定向。 选取调研对象&#xff1a;涉及多角色&#xff0c;一…

【吊打面试官系列-ZooKeeper面试题】zookeeper 负载均衡和 nginx 负载均衡区别?

大家好&#xff0c;我是锋哥。今天分享关于 【zookeeper 负载均衡和 nginx 负载均衡区别? 】面试题&#xff0c;希望对大家有帮助&#xff1b; zookeeper 负载均衡和 nginx 负载均衡区别? zk 的负载均衡是可以调控&#xff0c;nginx 只是能调权重&#xff0c;其他需要可控的都…

heic文件怎么转换成jpg?上百份文件转换3秒就能搞定(办公必备)

heic和jpg是两种不同的图片格式&#xff0c;平时整理图片素材时&#xff0c;如果需要将heic转为jpg格式&#xff0c;那么可以使用相关的heic图片转换工具。 ​ 为什么要将heic文件转换成jpg&#xff1f;虽然HEIC格式具有很多优点&#xff0c;但是目前并不是所有设备和应用程序…