/* * linux/kernel/printk.c * * (C) 1991 Linus Torvalds */
/* * When in kernel-mode, we cannot use printf, as fs is liable to * point to 'interesting' things. Make a printf with fs-saving, and * all is well. */ #include <stdarg.h> #include <stddef.h>
#include <linux/kernel.h>
static char buf[1024];
extern int vsprintf(char * buf, const char * fmt, va_list args); //只能在内核中使用,由于实际调用 的显示 函数tty_write默认使用的显示数据在段寄存器fs所指向的用户数据区中,因此这里可以暂时保存fs,并让fs指向内核数据段,再显示完成后再恢复fs断的内容。
int printk(const char *fmt, ...)//内核显示信息函数
{ va_list args; int i;
va_start(args, fmt);//开始传递可变参数,(可能不对)
i=vsprintf(buf,fmt,args);//将内容输入到buf中,返回值i等于输出字符串的长度
va_end(args);//结束,与va_start相对应
__asm__("push %%fs\n\t"//保存fs
"push %%ds\n\t"//
"pop %%fs\n\t"//fs==ds,ds为内核的数据段
"pushl %0\n\t"//字符串长度压入堆栈
"pushl $_buf\n\t"//将buf地址压入堆栈
"pushl $0\n\t"//将字符0压入堆栈,为显示 通道号channel
"call _tty_write\n\t"//调用tty_write函数
"addl $8,%%esp\n\t"//丢弃两个入栈参数,(buf,channel)
"popl %0\n\t"//弹出字符串的长度
"pop %%fs"//恢复原fs 寄存器
::"r" (i):"ax","cx","dx");//通知编译器,ax cx dx 寄存器的值可以已经改变
return i;//返回输出的字符个数
}
|