可变参数列表---以dbg()为例

时间:2023-03-10 06:01:21
可变参数列表---以dbg()为例

在UART驱动的drivers/serial/samsung.h中遇到如下定义:

#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG

extern void printascii(const char *);

static void dbg(const char *fmt, ...)
{
va_list va;
char buff[]; va_start(va, fmt);
vsprintf(buff, fmt, va);
va_end(va); printascii(buff);
} #else
#define dbg(x...) do { } while (0)
#endif

在samsung.c中是这样应用的:

dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",ch, uerstat);

1.对于void printascii(const char *);

有如下解释:

printk输出的log到串口上,配置串口用的是bootloader传过来的参数,例如console=ttyS0。

printascii是独立于printk的打印log的方法。printascii是汇编实现的,直接往uart发送寄存器里扔数据。所以在kernel开始,解析参数之前的log,就可以用printascii去看log.

为了支持 printascii()函数,需要在Kernel裁减中(make menuconfig)添加Kernel hacking-? [*]Kernel low-level debugging functions的支持。
2.关于#define dbg(x...) do { } while (0)

    避免空宏引起的warning

内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏。

3.可变参数列表dbg(const char *fmt, ...),通过定义于stdarg.h中的宏来实现。

  包括一个类型va_list和三个宏--va_start、va_arg和va_end。

  (1)va_list va;

  (2)va_start(va, fmt);//初始化va,使va指向可变参数部分的第一个参数。

  (3)ret=va_arg(va,char);//此处本代码未利用

      //va_arg()第一个参数是va_list变量,第二个参数是参数列表里下一个参数的类型

       //va_arg返回这个参数的值,并使va_arg指向下一个可变参数

  (4)va_end(va);//完成处理

4.vsprintf()

送格式化输出到串中