ucore的字符输出有cga,lpt,和串口。qemu模拟出来显示器连接到cga中。
cga
cga的介绍网站:https://en.wikipedia.org/wiki/Color_Graphics_Adapter
cga是显示卡,内部有个叫6845的芯片。cga卡把屏幕划分成一个一个单元格,每个单元格显示一个ascii码编码的字符。cga显示卡关注内存中某一段特定地址的数据,并显示这些数据。CPU只需要把要显示的字符编码放到显示卡关注的内存中。cga能显示的数据有格式要求,另外,它能显示的东西很少。如果CPU是以cga这种方式控制屏幕,是无法控制屏幕上的每一个像素的。cga的优点在于方便地显示字符。程序员唯一需要知道的知识就是字符编码。
ucore的字符串输出函数
cprintf和snprintf是操作系统使用者调用的函数。正常来说,是不会直接调用vcprintf和vsnprintf以及它右边的函数的。
cprintf是向控制台输出字符串,snprintf是向内存buffer输出字符串。
cprintf
cprintf的用法和c标准库printf的用法完全一致。
/* *
* cprintf - formats a string and writes it to stdout
*
* The return value is the number of characters which would be
* written to stdout.
* */
int cprintf(const char *fmt, ...) {
va_list ap;
int cnt;
va_start(ap, fmt);
cnt = vcprintf(fmt, ap);
va_end(ap);
return cnt;
}
cprintf的工作很简单,它就是把可变参数变成va_list。就把剩下的工作交给vcprintf了。
vcprintf
vcprintf负责为vcprintfmt选择一个输出出口,选择的输出出口为控制台。并把格式解析工作交给vcprintfmt。
下面的cputch就是控制台输出函数。这个函数将向控制台输出一个字符。
int vcprintf(const char *fmt, va_list ap) {
int cnt = 0;
vprintfmt((void*)cputch, &cnt, fmt, ap);
return cnt;
}
vprintfmt
这个函数就是解析fmt,使得变成一个直接的字符串,然后调用上一个函数传来的出口函数,一个一个地将解析好的字符输出。如果要了解是如何解析格式的,看的就是这个函数。
cputch
/* *
* cputch - writes a single character @c to stdout, and it will
* increace the value of counter pointed by @cnt.
* */
static void
cputch(int c, int *cnt) {
cons_putc(c);
(*cnt) ++;
}
cons_putc
向lpt,cga,串口各输出一个字符,调用的三个函数可以理解为外设的驱动了。这三个函数是和硬件打交道的函数。
/* cons_putc - print a single character @c to console devices */
void
cons_putc(int c) {
lpt_putc(c);
cga_putc(c);
serial_putc(c);
}