您的位置:首页 > 运维架构 > Linux

linux内核中printf函数实现原理分析

2015-04-03 10:44 295 查看
首先看printf函数的定义:
1 static int printf(const char *fmt, ...)
2 {
3 va_list args;
4 int i;
5
6 va_start(args, fmt);
7 write(1,printbuf,i=vsprintf(printbuf, fmt, args));
8 va_end(args);
9 return i;
10 }
参数中采用了可变参数的定义,可变参数的一系列实现函数va函数如下:va_list arg_ptr;void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变量是指向参数的指针。然后使用va_start使arg_ptr指针指向prev_param的下一位,然后使用va_args取出从arg_ptr开始的type类型长度的数据,并返回这个数据,最后使用va_end结束可变参数的获取。
我们可以看下可变参数调用原理:C语言中,参数压栈的方向是从右往左。也就是说,当调用printf函数的适合,先是最右边的参数入栈。fmt是一个指针,这个指针指向第一个const参数(const char *fmt)中的第一个元素。
fmt也是个变量,它的位置,是在栈上分配的,它也有地址。
对于一个char *类型的变量,它入栈的是指针,而不是这个char *型变量。
可变参数函数调用原理(其中涉及的数字皆为举例)
=========================================================================================
i = 0x23;
j = 0x78;
char fmt[] = "%x%d";
printf(fmt, i, j);

push    j
push    i
push    fmt
call    printf
add     esp, 3 * 4

┃        HIGH        ┃                        ┃        HIGH        ┃
┃        ...         ┃                        ┃        ...         ┃
┣━━━━━━━━━━┫                        ┣━━━━━━━━━━┫
┃                    ┃                 0x32010┃        '\0'        ┃
┣━━━━━━━━━━┫                        ┣━━━━━━━━━━┫
0x3046C┃        0x78        ┃                 0x3200c┃         d          ┃
┣━━━━━━━━━━┫                        ┣━━━━━━━━━━┫
arg = 0x30468┃        0x23        ┃                 0x32008┃         %          ┃
┣━━━━━━━━━━┫                        ┣━━━━━━━━━━┫
0x30464┃      0x32000 ───╂────┐       0x32004┃         x          ┃
┣━━━━━━━━━━┫        │              ┣━━━━━━━━━━┫
┃                    ┃        └──→ 0x32000┃         %          ┃
┣━━━━━━━━━━┫                        ┣━━━━━━━━━━┫
┃        ...         ┃                        ┃        ...         ┃
┃        LOW         ┃                        ┃        LOW         ┃

实际上,调用 vsprintf 的情形是这样的:

vsLprintf(buf, 0x32000, 0x30468);

*****************************************************************************************
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 可变参数 printf