Linux内核打印printk

本文介绍了Linux内核中的printk函数,其提供了灵活的格式化输出,支持8个打印级别。还详细讲解了console_printk数组和如何查看当前控制台的日志级别设置。


本文将展开介绍内核打印函数printk
printk函数是Linux内核中常用的记录消息的函数之一。能在任何上下文中使用,并提供灵活的格式化输出功能。通过使用 printk函数,开发者可以在内核代码中记录关键消息,进行调试以及了解系统的运行状况。

函数原型

/**
 * printk - print a kernel message
 * @fmt: format string
 *
 * This is printk(). It can be called from any context. We want it to work.
 *
 * We try to grab the console_lock. If we succeed, it's easy - we log the
 * output and call the console drivers.  If we fail to get the semaphore, we
 * place the output into the log buffer and return. The current holder of
 * the console_sem will notice the new output in console_unlock(); and will
 * send it to the consoles before releasing the lock.
 *
 * One effect of this deferred printing is that code which calls printk() and
 * then changes console_loglevel may break. This is because console_loglevel
 * is inspected when the actual printing occurs.
 *
 * See also:
 * printf(3)
 *
 * See the vsnprintf() documentation for format string extensions over C99.
 */
asmlinkage __visible int printk(const char *fmt, ...)
{
	printk_func_t vprintk_func;
	va_list args;
	int r;

	va_start(args, fmt);

	/*
	 * If a caller overrides the per_cpu printk_func, then it needs
	 * to disable preemption when calling printk(). Otherwise
	 * the printk_func should be set to the default. No need to
	 * disable preemption here.
	 */
	vprintk_func = this_cpu_read(printk_func);
	r = vprintk_func(fmt, args);

	va_end(args);

	return r;
}
EXPORT_SYMBOL(printk);

printk函数使用asmlinkage__visible修饰符,表示这是一个可见的内联函数,并可以在任意上下文中调用。
EXPORT_SYMBOL(printk)表示将printk函数导出为符号,使得其他模块能够使用该函数。

打印级别

共有如下8个级别,这些宏通常与printk函数一起使用,用于在内核中输出不同级别的消息到系统日志。

#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 KERN_DEFAULT	KERN_SOH "d"	/* the default kernel loglevel */ 

默认打印级别

console_printk数组

Linux内核源代码中,console_printk是一个名为console_printk的整型数组。该数组的定义如下所示:

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

其中,数组console_printk的四个元素依次表示以下意义的值:

  1. console_loglevel:控制台(console)输出日志的级别。
  2. default_message_loglevel:默认消息日志级别。
  3. minimum_console_loglevel:最小控制台日志级别。
  4. default_console_loglevel:默认控制台日志级别。

这些值在内核的初始化阶段被用于设定控制台输出日志的级别。这些级别控制了内核消息何时会被输出到系统的控制台上。

在这个数组中,CONSOLE_LOGLEVEL_DEFAULTMESSAGE_LOGLEVEL_DEFAULT分别代表控制台和消息的默认日志级别,而CONSOLE_LOGLEVEL_MIN代表最小的控制台日志级别。

这些值是Linux内核中用于控制内核消息输出的重要参数,在调试系统问题和进行日志记录时起着关键作用。

查看当前控制台的打印级别

cat /proc/sys/kernel/printk

输出的内容通常是一个由空格分隔的四个整数,分别表示以下意义的值:

  1. 控制台(console)输出日志的最小级别
  2. 默认消息日志级别
  3. 控制台输出日志的最小级别
  4. 默认控制台日志级别

输出可能是类似这样的信息:

4       4       1       7

与上面的console_printk数组对应

<think>首先,用户的问题是:“linux内核printk也是这样么”,这是在询问Linux内核中的printk函数是否也使用像用户空间中printf那样的格式说明符,比如%hu。 回顾对话历史: - 用户之前问了关于printf中打印unsigned short使用%hu的问题。 - 我现在需要回答这个问题,然后根据问题和回答提出3-5个相关问题。 我的回答需要: 1. 用中文回答问题。 2. 在回答后,提出3-5个相关问题。 3. 第一行必须是完整的“§§相关问题§§”,不能换行分散。 4. 确保所有内容符合规则。 针对问题:“linux内核printk也是这样么” - 这是在Linux内核上下文中,printk函数是否也使用%hu来打印unsigned short? - printk内核中的打印函数,类似于printf,但有一些差异。 - 在Linux内核中,printk支持大部分printf的格式说明符,但可能有细微差别。 - 对于unsigned short,理论上应该可以使用%hu,因为printk基于vsnprintf,它支持标准C格式。 - 但是,在Linux内核中,printk有特定的扩展和限制。 - 具体回答:是的,printk也支持%hu来打印unsigned short类型。 完整回答结构: - 先回答问题。 - 提供一个代码示例(如果需要)。 - 然后以“§§相关问题§§”开头,列出3-5个相关问题。 相关问题必须基于用户的问题和我的回答: - 用户的问题是关于printk是否像printf那样使用格式说明符。 - 我的回答会确认这一点,并可能提及内核中的差异。 - 所以,相关问题可以涉及printk的用法、格式、内核特性等。 脑力 storm 相关问题: 1. printk和printf有什么区别? 2. 在内核中处理unsigned short时需要注意什么? 3. printk支持哪些额外的格式说明符? 4. 如何在内核打印其他数据类型? 5. printk的日志级别如何工作? 6. 为什么内核使用printk而不是printf? 确保3-5个问题。 最终回答: - 回答问题:是的,在Linux内核中,printk函数也支持使用%hu来打印unsigned short类型变量,类似于用户空间中的printf。但需要注意内核中的一些特定行为和限制。 - 示例代码(如果需要):可以提供一个简单的例子,比如在驱动中使用printk。 - 然后输出“§§相关问题§§”,列出问题。 代码示例建议: - 既然用户提到了内核,我可以给一个printk的使用例子。 例如: ```c unsigned short value = 42; printk(KERN_INFO "Value: %hu\n", value); ``` 相关问题列表(3-5个): 1. printk和printf的主要区别是什么? 2. 在Linux内核中,如何设置printk的日志级别? 3. unsigned short在内存对齐方面有何考虑? 4. printk是否支持所有标准C格式说明符? 5. 如何处理printk输出的日志消息? 确保第一行是“§§相关问题§§”,不能换行。 输出格式: - 回答内容。 - 然后直接“§§相关问题§§” - 接着问题列表,每个问题一行。 </think>在Linux内核中,`printk`函数与用户空间的`printf`类似,支持大部分格式说明符,包括`%hu`用于打印`unsigned short`类型。例如: ```c unsigned short value = 65535; printk(KERN_INFO "Value: %hu\n", value); ``` - `%hu`在`printk`中有效,工作原理与`printf`一致。 - 区别在于`printk`专注于内核日志,支持日志级别(如`KERN_INFO`),且输出到内核缓冲区(如`dmesg`查看),而非终端输出。 - 注意:内核代码必须确保类型匹配,避免因格式错误导致崩溃或日志混乱。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值