打印版本信息

本文探讨了Linux内核中printk函数的工作原理,它用于在屏幕上打印信息。通过分析kernel/printk.c中的源码,揭示了printk、va_start、vprintk和va_end如何协作处理可变参数。printk首先将信息存储在4k大小的缓冲区中,如果console已初始化,则通过console->write函数输出,否则信息保留在缓冲区等待后续查看。

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

5.1.6 打印版本信息

我们来简单的看看在内核中,在屏幕上打印一条信息的原理是怎么实现的。由于我们配置了CONFIG_PRINTK编译选项,所以调用位于kernel/printk.c中的printk函数:

 

584 asmlinkage int printk(const char *fmt, ...)

585 {

586        va_list args;

587        int r;

588 

589        va_start(args, fmt);

590        r = vprintk(fmt, args);

591        va_end(args);

592

593        return r;

594}

 

又看到了”,不错跟刚才讲的可变参数宏差不多只不过这里是可变参函数。那么start_kernel中调用的printk(KERN_NOTICE "%s", linux_banner)其中linux_banner是个全局字符串常量定义在init/version.c

const char linux_banner[] =

       "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"

       LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "/n";

 

上面那些大写的东西都在我们顶层Makefile中定义过了,就是一些版本信息,整个函数的功能没有问题,我们主要关注本质。所以来看看va_startvprintkva_end是怎么协作的。

 

首先,va_list并不是一个什么复杂的数据结构,而是:

typedef char *va_list;

仅仅就是一个char*。所以,根据va_start的定义:

#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))

#define va_arg(ap, T)         /

  (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))

这就是一个可变参数的调整。调整好以后,我们就可以使用它了。

 

665asmlinkage int vprintk(const char *fmt, va_list args)

 666{

<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值