3. 库函数的实现

声明: 此系列文章尚未完成,请勿转载,谢谢合作

梗概
这一节新增的文件有:
stdarg.h       用来处理可变参数
ctype.h        判断变量一些属性。比如一个字符是不是大写,是不是数字
string.h string.c      常用的关于字符串的操作
vsprintf.h vsprintf.c       该节的主要文件用来实现格式化输出
改变的文件有:
test.c         主要用来测试 printk函数


正文

大家上程序设计课程写的第一个程序应该是hello world吧,它仅仅是用printf函数打印一条问候语句,是的,非常简单。但是想在内核中用printf可就没那么容易了,因为内核程序根本就不能使用C库函数,但是printf函数却又非常重要。怎么办?大家应该还记得上一节写的vga驱动,用它直接打印不就得了。醒醒吧,printf可没那么简单,它不仅要能打印字符串,还要控制格式,就像这样: printf("Tinux is %d years old.", 2)。cons_write函数可不会把%d替换成数字2。看来还是要自己动手,才能丰衣足食了。

本节目标就是实现printf函数,不过我给它取了另一个名字叫printk,以表明它是用在内核当中的printf函数。另外还会有些附带的函数产品,像strcpy,memcpy等字符串操作函数,sprintf,vsprintf等底层打印函数。printk函数就是靠vsprintf实现的。

可变参数的头文件 stdarg.h
请拿出你的C语言参考书,看一下printf函数的声明: int printf(const char *format, ...);
是的,这就是传说中的变长参数。我在这里只提供变长参数的大概知识,详情请看变长参数的实现。变长参数涉及一个自定义的数据类型va_list,和三个宏定义va_start, va_arg, va_end。他们都定义在头文件stdarg.h中,我是直接通过gcc内置宏定义的,与链接给出的文章不同,因为那篇文章是为了讲解变长参数,真正实现时用gcc内置宏就可以了,相当于gcc内置宏为我们做好了定义,这样正确率更高,要知道调试OS Kernel可是相当烦。
stdarg.h

C类型头文件 ctype.h
里面都是些常用宏,比如 islower(c)判断c是不是小写字母,isdigit(c)判断c是不是十进制数码,isxdigit(c)判断c是不是十六进制数码
isspace(c)判断c是不是空白字符
ctype.h

字符串处理 string.h string.c
关于 memcpy函数和mememove函数的区别请自行Google
string.h

string.c

打印函数 vsprintf.h vsprintf.c
vsprintf.h

vsprintf.c

这一节的程序和上节的一样,起基础作用,并没有关系到进程,内存管理等OS核心理论。但是它们的正确与否至关重要,这也是OS研究的繁琐之处,想要一探它的奥秘还必须先做一些杂七杂八的玩意儿。

测试程序 test.c
让该程序做一些算术题目,并格式化输出结果

test.c



运行结果如下:
                

PS: 此节的程序几乎全部来自CROCOS, 这是个开源OS项目, 它的新颖之处在于OS开发方式, 先像开发用户程序一样开发OS组件,最后再移到真实的硬件环境中。
    若有兴趣,请访问 http://crocos.sourceforge.net/


Tinux Kernel源码下载 Tinux3.zip

posted on 2009-11-08 12:24  John Waken  阅读(1832)  评论(0编辑  收藏  举报

导航