Linux102系列会详细讲解Linux0.11版本中的102个文件,本文讲解linux0.11的第10个文件
kernel/printk.c的文件源码。
1.printk的主要作用
一句话:就是内核态的printf。
其中,printk会使用到的函数:
| vsprintf | 移步:☺【Linux102】11-kernel/vsprintf.c |
| stdarg.h头文件 | 移步:☺【Linux102】12-include/stdarg.h |
3.源码注释版本
/*
* 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];
/**
* @brief 格式化字符串函数,并且返回格式化后的字符串长度
*
* @param buf 输出缓冲区
* @param fmt 格式化字符串
* @param args 可变参数列表
* @return int 输出字符串的长度
*/
extern int vsprintf(char *buf, const char *fmt, va_list args);
/**
* @brief 打印内核消息函数
*
* @param fmt 格式化字符串
* @return int 输出字符串的长度
* 注意:printk负责格式化,tty_write负责硬件相关的实际写入,职责分离使代码更易维护。
*/
int printk(const char *fmt, ...)
{
va_list args; /*可变参数列表指针*/
int i;
/*初始化可变参数列表指针*/
va_start(args, fmt);
/*格式化字符串长度*/
i = vsprintf(buf, fmt, args);
/*结束可变参数列表指针*/
va_end(args);
/*使用 GCC 内联汇编直接操作硬件和调用内核函数tty_write输出内容*/
__asm__("push %%fs\n\t" /*保存fs寄存器*/
"push %%ds\n\t" /*保存ds寄存器*/
"pop %%fs\n\t" /*恢复fs寄存器*/
"pushl %0\n\t" /*压入字符串长度i作为参数*/
"pushl $buf\n\t" /*压入缓冲区地址作为参数*/
"pushl $0\n\t" /*压入文件描述符0(通常代表控制台)*/
"call tty_write\n\t" /*调用tty_write函数*/
"addl $8,%%esp\n\t" /*清理栈上的两个参数,返回值依旧保留的*/
"popl %0\n\t" /*恢复i的值*/
"pop %%fs\n\t" /*恢复fs寄存器*/
: /*没有实际的输出寄存器*/
: "r"(i) /*输入:将i放入寄存器.注意这里没有输出*/
: "ax", "cx", "dx");/*告知编译器这些寄存器(ax cs dx)会被修改*/
return i;
}
4.源码源版本
/*
* 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);
int printk(const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
i = vsprintf(buf, fmt, args);
va_end(args);
__asm__("push %%fs\n\t"
"push %%ds\n\t"
"pop %%fs\n\t"
"pushl %0\n\t"
"pushl $buf\n\t"
"pushl $0\n\t"
"call tty_write\n\t"
"addl $8,%%esp\n\t"
"popl %0\n\t"
"pop %%fs" ::"r"(i) : "ax", "cx", "dx");
return i;
}
5.源码图像版本



😉【C语言】C语言的关键字与重载机制
😉【C语言】长字符串的2种处理方式
专注讲解Linux中的常用命令,共计发布100+文章。
本系列将精讲Linux0.11内核中的每一个文件,共计会发布100+文章。
😉【Linux102】11-kernel/vsprintf.c
😉【Linux102】12-include/stdarg.h
和Linux内核102系列不同,本系列将会从全局描绘Linux内核的各个模块,而非逐行源码分析,适合想对Linux系统有宏观了解的家人阅读。
😉【Linux】Linux概述1-linux对物理内存的使用
关于小希
😉嘿嘿嘿,我是小希,专注Linux内核领域,同时讲解C语言、汇编等知识。
我的微信:C_Linux_Cloud,期待与您学习交流!

加微信请备注哦
小希的座右铭:
别看简单,简单也是难。别看难,难也是简单。我的文章都是讲述简单的知识,如果你喜欢这种风格:
下一期想看什么?在评论区留言吧!我们下期见!


被折叠的 条评论
为什么被折叠?



