Linux内核日志分级

本文详细介绍了Linux内核中的printk日志分级,包括定义、使用和设置。讨论了如何设置控制台console的级别,并展示了如何在用户空间修改这些设置。此外,还探讨了自定义printk分级的实现,包括定义新的custom_printk接口、使用方法及设置控制日志打印的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内核printk分级

定义

  内核代码source/kernel_src/kernel/kernel-4.9/include/linux/kernel.h中,定义了控制台console的级别:

#define CONSOLE_LOGLEVEL_SILENT  0 /* Mum's the word */
#define CONSOLE_LOGLEVEL_MIN     1 /* Minimum loglevel we let people use */
#define CONSOLE_LOGLEVEL_QUIET   4 /* Shhh ..., when booted with "quiet" */
#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */
#define CONSOLE_LOGLEVEL_DEBUG  10 /* issue debug messages */
#define CONSOLE_LOGLEVEL_MOTORMOUTH 15  /* You can't shut this one up */

extern int console_printk[];
#define console_loglevel (console_printk[0])
#define default_message_loglevel (console_printk[1])
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])
#define default_devkmsg_loglevel (console_printk[4])

  内核代码source/kernel_src/kernel/kernel-4.9/kernel/printk/printk.c中,定义了console_printk结构体:

int console_printk[5] = {
	CONSOLE_LOGLEVEL_DEFAULT,       /* console_loglevel */
	MESSAGE_LOGLEVEL_DEFAULT,       /* default_message_loglevel */
	CONSOLE_LOGLEVEL_MIN,           /* minimum_console_loglevel */
	CONSOLE_LOGLEVEL_DEFAULT,       /* default_console_loglevel */
	MESSAGE_LOGLEVEL_DEFAULT,       /* default_devkmsg_loglevel */
};

使用

  内核中使用printk函数时加上信息级别,例如:

printk(KERN_WARNING "there is a warning here!\n");

  KERN_WARNING就表示信息的级别,相关宏在函数source/kernel_src/kernel/kernel-4.9/include/linux/kernel.h中定义:

#define KERN_SOH        "\001"          /* ASCII Start Of Header */

#define KERN_EMERG      KERN_SOH "0"    /* system is unusable 				*/
#define KERN_ALERT      KERN_SOH "1"    /* action must be taken immediately */
#define KERN_CRIT       KERN_SOH "2"    /* critical conditions 				*/
#define KERN_ERR        KERN_SOH "3"    /* error conditions 				*/
#define KERN_WARNING    KERN_SOH "4"    /* warning conditions 				*/
#define KERN_NOTICE     KERN_SOH "5"    /* normal but significant condition */
#define KERN_INFO       KERN_SOH "6"    /* informational 					*/
#define KERN_DEBUG      KERN_SOH "7"    /* debug-level messages 			*/

  如果没有指明信息级别的话,就会采用默认的信息级别:

#define default_message_loglevel (console_printk[1])

设置

  控制台console的级别默认是"6 6 1 7 4",可以修改用户空间的/proc/sys/kernel/printk,例如:

echo “1	1 4 1 7> /proc/sys/kernel/printk

自定义printk分级

  在工作中,log分级只需要划分debug和release,因此设计自定义的printk分级。

定义

  添加source/kernel_src/kernel/custom/include/linux/custom_debug.h,定义custom_printk:

#define CUSTOM_ERROR(f, arg...) \
	printk(KERN_ERR "custom_error: %s->%s->%d: " f, __FILE__, __func__, __LINE__, ## arg)

#define CUSTOM_WARNING(f, arg...) \
	printk(KERN_WARNING  "custom_warning: " f, ## arg)

#define CUSTOM_NOTICE(f, arg...) \
	printk(KERN_NOTICE  "custom_notice: " f, ## arg)

#define CUSTOM_INFO(f, arg...) \
	printk(KERN_INFO  "custom_info: " f, ## arg)
        
#define CUSTOM_DEBUG(f, arg...) \
	do { \
		if (custom_loglevel) \		// 修改Makefile, 编译时添加到generated.h
			printk(KERN_DEBUG "custom_debug: %s->%s->%d: " f, __FILE__, __func__, __LINE__, ## arg); \
	}while (0)

接口

  添加cutom_printk.c

#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/custom_debug.h>

int custom_loglevel = CUSTOM_DEBUG_ON;
static char *custom_printk[] = {"release", "debug"};


static int loglevel_proc_show(struct seq_file *m, void *v)
{
	seq_printf(m, "%s\n", custom_printk[custom_loglevel]);

	return 0;
}

static int loglevel_proc_open(struct inode *inode, struct file *file)
{
	return single_open(file, loglevel_proc_show, NULL);
}

static ssize_t loglevel_proc_write(struct file *file, const char *buffer, unsigned long count, loff_t *pos)
{
	unsigned long ret = count;
	char *log_type = kzalloc(10, GFP_KERNEL);

	if (copy_from_user((void *)log_type, (const void __user *)buffer, count))
		ret = -EFAULT;

	if (sysfs_streq(log_type, custom_printk[0]))		// release
		custom_loglevel = 0;
	else if (sysfs_streq(log_type, custom_printk[1]))	// debug
		custom_loglevel = 1;
	else
		ret = -EINVAL;

	kfree(log_type);
	return ret;
}

static const struct file_operations loglevel_proc_fops = {
	.open		= loglevel_proc_open,
	.write		= loglevel_proc_write,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};

static int __init proc_loglevel_init(void)
{
	proc_create("loglevel", 0666, NULL, &loglevel_proc_fops);

	return 0;
}
fs_initcall(proc_loglevel_init);

使用

// 包含头文件
#include <linux/custom_debug.h>

// 打印一般信息
CUSTOM_INFO("%s: the platform-name is %s\n", __func__, str);

// 打印错误信息
CUSTOM_ERROR("%s: no platform-name property\n", __func__);

// 打印DEBUG信息
CUSTOM_DEBUG("%s", __func__);

设置

  修改用户空间的/proc/loglevel,可以控制是否打印log(到console和syslog):
loglevel只控制CUSTOM_DEBUG

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值