printf
ypedef char* va_list;
//确保内存对齐
#define __va_round_size(TYPE) (((sizeof(TYPE)+sizeof(int)-1)/sizeof(int))*sizeof(int))
//在可变参数函数的实现中用于设置 va_list 的起始位置。
#define va_start(AP, LASTARG) (AP = ((char*) &(LASTARG) + __va_round_size(LASTARG)))
const char printfbuf[1024]
static int printf(const char *fmt,...){
va_list args;
int i;
va_start(args, fmt);
//int write(int fildes, const char * buf, off_t count);
write(1, printfbuf,i=vsprintf(printfbuf, fmt, args));
va_end(args);
return i;
}
_syscall3(int,write,int,fd,const char *,buf,off_t,count)
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
{ \
type __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" (a),"c" (b),"d" (c)); \
if (__res<0) \
errno=-__res , __res = -1; \
return __res;\
}
printk
printk()是内核中使用的打印函数,功能与C标准函数库中的printf()相同。重新编写这么一个函数的原因是在内核代码中不能直接使用专用于用户模式的fs段寄存去,而需要首先保存它
不能直接使用fs的原因是由于在实际屏幕显示函数tty_write()中,需要被显示的信息取自于fs段指向的数据段中,即用户程序数据段中
而printk()函数中需要显示的信息是在内核数据段中,即在内核代码中执行时ds指向的内核数据段中。因此在printk中需要临时使用一下fs段寄存器