printk.c

818阅读 0评论2009-08-05 jhluroom
分类:LINUX

/*
 * 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;//返回输出的字符个数

}

上一篇:vsprintf.c
下一篇:panic.c