Linux最小系统移植之早期打印CONFIG_EARLY_PRINTK

本文详细解析了Linux系统中eraly_printk的实现机制,包括其配置选项、源码分析及测试验证过程。eraly_printk通过封装printch()函数,实现了在系统早期阶段的格式化打印功能,极大地方便了调试工作。

 

  请先参考先前博文:  Linux最小系统移植之早期打印CONFIG_DEBUG_LL  , 因为eraly_printk其实就是对printch()封装的

一、 必要选项(在上面链接选中的前提下再新增CONFIG_EARLY_PRINTK):

/* linux-3.10.65/arch/arm/kernel/Makefile */
obj-$(CONFIG_DEBUG_LL)    += debug.o
obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o

 

 二、源码分析

  先贴出early_printk.c源码:

/*
 *  linux/arch/arm/kernel/early_printk.c
 *
 *  Copyright (C) 2009 Sascha Hauer <s.hauer@pengutronix.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/init.h>

extern void printch(int);

static void early_write(const char *s, unsigned n)
{
    while (n-- > 0) {
        if (*s == '\n')
            printch('\r');
        printch(*s);
        s++;
    }
}

static void early_console_write(struct console *con, const char *s, unsigned n)
{
    early_write(s, n);
}

static struct console early_console_dev = {
    .name =        "earlycon",
    .write =    early_console_write,
    .flags =    CON_PRINTBUFFER | CON_BOOT,
    .index =    -1,
};

static int __init setup_early_printk(char *buf)
{
    early_console = &early_console_dev;
    register_console(&early_console_dev);
    return 0;
}

early_param("earlyprintk", setup_early_printk);

  以及调用的地方:

/* linux-3.10.65/kernel/printk.c */
void early_vprintk(const char *fmt, va_list ap)
{
    if (early_console) {
        char buf[512];
        int n = vscnprintf(buf, sizeof(buf), fmt, ap);

        early_console->write(early_console, buf, n);
    }
}

asmlinkage void early_printk(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    early_vprintk(fmt, ap);
    va_end(ap);
}
#endif

 

1. 调用者使用early_printk()可变参数打印函数
2. 函数的参数是存放在栈中的,由于是可变参数, 请问怎么知道栈存放多少参数? --> 使用va_start()解析
 其原理根据第一个参数fmt的地址,以及最后一个参数ap地址知道这块栈区域都是形参, 记得变量ap要放在函数
 第一行表示形参结束。同时,为确保所有参数都是放置栈(GCC编译器默认把前四个形参放置R0/1/2/3,后面才放入栈中)
 定义了asmlinkage, 告知编译器全部形参放置栈中
3. vscnprintf()作用就是解析%d,%x, int a等格式, 最终全部转为字符放置buf中, 再调用early_console->write()输出
4. CON_PRINTBUFFER 打印缓冲所有数据, 如果后续串口驱动也设置这个标志, printk会重复打印eraly_printk 打的,CON_BOOT表示在启动期间有效
5. early_param("earlyprintk", setup_early_printk); 说明uboot或者DTB传给kernle 的 cmdline要有这个字段才能生效
6. 由于early_param是在start_kernel() -> parse_args() 的unknown_bootoption()处理的, 所以必须放置这个函数之后才能使用, 否则early_printk()就是空函数

7. 与printascii() printch()最大不同在于eraly_printk()可以打印格式参数%d, %p等, 方便调试

 

三、测试验证

  

  

  

  

  测试发现确实只有2打印出来, 1没有

 

转载于:https://www.cnblogs.com/vedic/p/10749745.html

### Linux 内核配置宏的功能解析 #### 1. CONFIG_KASAN=y `CONFIG_KASAN=y` 表示启用了 Kernel Address Sanitizer (KASan)[^2]。这是 Linux 内核中的一种动态内存错误检测工具,旨在帮助开发者快速找到并修复内核中的内存访问错误。它通过在编译时插入额外的检查逻辑,在运行时监控所有的内存访问操作,一旦发现有越界访问或者非法使用已释放内存的情况,就会立即报告错误信息。 #### 2. CONFIG_KASAN_STACK=y 此选项作为 KASan 的扩展特性之一,专门用于加强对栈区内存使用的监测力度[^3]。当设置为 `y` 时表示不仅常规堆分配对象受到严格管控,就连临时存在于函数调用过程中的局部变量也同样纳入审查范畴之内。这有助于捕捉那些难以察觉却极其危险的栈溢出问题以及其他形式的栈破坏行为。 #### 3. Other Related Configurations 除了上述两个主要参数外,还有几个密切关联的选择项也值得探讨: - **CONFIG_KASAN_GENERIC**: 如果定义成'y'则意味着采用通用版本的KASan实现方式;反之如果是'n'(即关闭状态),那么可能会切换至更高效的硬件加速型变体(取决于体系结构支持状况)[^4]. - **CONFIG_KASAN_OUTLINE**: 当此项设为'y',将会把大部分复杂的错误探测工作转移到单独生成的小型子程序里完成,这样可以减少主路径上的性能损失;但如果将其置为'n',则倾向于将这些附加检验直接嵌入原始代码流之中. - **CONFIG_KASAN_INLINE**: 和上面提到的那个形成互补关系——当且仅当两者都选'true'的时候才会生效。它的存在主要是为了让某些特定条件下能够获得更好的速度表现(比如针对小型数据结构频繁短时间存活的情形). ```python # Example configuration snippet showing interplay between different KASAN options. if CONFIG_KASAN == "y": if CONFIG_KASAN_GENERIC == "y": # Use generic implementation... elif CONFIG_KASAN_HW_TAGS == "y": # Utilize hardware tagging features instead... if CONFIG_KASAN_OUTLINE == "y": # Offload complex checks to helper functions... else: # Inline all possible verifications directly into mainline code paths... if CONFIG_KASAN_INLINE == "y" and CONFIG_KASAN_OUTLINE != "y": # Optimize specifically for inline scenarios where feasible... ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值