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_start、vprintk和va_end是怎么协作的。
首先,va_list并不是一个什么复杂的数据结构,而是:
typedef char *va_list;
仅仅就是一个char*。所以,根据va_start的定义:
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) /