ucore的字符输出

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
任务描述 在了解管道读写基本原理的基础上,完善pipewrite()函数,实现内核线程之间的通信。 相关知识 你需要了管道的读写原理,以下是关于管道读与管道写功能的介绍。 pipewrite()函数介绍 // LAB5 CODES for communication int pipewrite(struct pipe *pi, char* msg, int len) { // w 记录已经写的字节数 int w = 0; while(w < len){ // 若不可读,写也没有意义 if(pi->readopen == 0){ return -1; } if(pi->nwrite == pi->nread + PIPESIZE){ // pipe write 端已满,阻塞 do_yield(); } else { // 一次读的 size 为 min(用户buffer剩余,pipe 剩余写容量,pipe 剩余线性容量) int size = MIN3( len - w, pi->nread + PIPESIZE - pi->nwrite, PIPESIZE - (pi->nwrite % PIPESIZE) ); kprintf("size %d\n",size); //LAB5 YOUR CODE EX2 ----------------- //LAB5 YOUR CODE EX2 ----------------- } } return w; } 函数用于将数据写入管道。它的工作流程如下: 1.初始化:w 变量记录已经写入的字节数。 2.循环写入:在循环中,不断将数据从用户缓冲区写入管道,直到所有数据都写入完毕或者遇到阻塞。 3.检查读端是否打开:如果读端关闭(pi->readopen == 0),写操作无效,返回 -1。 4.检查管道是否已满:如果管道已满(pi->nwrite == pi->nread + PIPESIZE),调用 do_yield() 进行让出处理器时间片,等待空间可用。 5.计算可写入的大小:使用 MIN3 宏计算一次写入的最大字节数,这取决于用户缓冲区剩余大小、管道剩余空间大小以及环形缓冲区的线性剩余容量。 6.写入数据:将数据从用户缓冲区复制到管道缓冲区,并更新写指针 pi->nwrite 和已写入字节数 w。 piperead()函数介绍 int piperead(struct pipe *pi, int n) { // r 记录已经写的字节数 int r = 0; // 若 pipe 可读内容为空,阻塞或者报错 while(pi->nread == pi->nwrite) { if(pi->writeopen) do_yield(); else return -1; } uint64_t size = MIN3( n - r, pi->nwrite - pi->nread, PIPESIZE - (pi->nread % PIPESIZE) ); while(r < n && size!=0){ kprintf("size %d\n",size); // pipe 可读内容为空,返回 if(pi->nread == pi->nwrite) break; // 一次写的 size 为:min(用户buffer剩余,可读内容,pipe剩余线性容量) int x=0; for (;x<size;x+=1){ kprintf("%c",*(pi->addr+r+x)); } pi->nread += size; r += size; } return r; } 该函数用于从管道中读取数据。它的工作流程如下: 1.初始化:r 变量记录已经读取的字节数。 检查管道是否为空:如果管道为空,且写端打开,调用 do_yield() 等待数据;如果写端关闭,返回 -1。 2.计算可读取的大小:使用 MIN3 宏计算一次读取的最大字节数,这取决于用户缓冲区剩余大小、管道中可读数据大小以及环形缓冲区的线性剩余容量。 3.读取数据:将数据从管道缓冲区复制到用户缓冲区,并更新读指针 pi->nread 和已读取字节数 r。 环形缓冲区实现 环形缓冲区是一种固定大小的缓冲区,它的读写指针可以在缓冲区的两端循环使用。在上述实现中,pi->nwrite 和 pi->nread 分别是写指针和读指针。通过对这些指针取模操作(% PIPESIZE),实现了环形效果。 如何填写代码 参考piperead函数的实现方式,用for循环对大小为size的空间进行写入,写入地址为*(pi->addr+w+x)(w是已经写入的空间,x是当前for循环遍历到的位置),写入值为*(msg+x+w)。 写入完成后需要将pipe已经写入的统计量nwrit加上size即:pi->nwrite += size;;并将本次写入的大小w加上size,即w += size; 在本小节,你需要编译代码,并查看输出结果。 输出结果说明 在调用该pipe的进程中,有如下的输入信息 lab5_proc0(void *arg) { struct trapframe *tf =current->tf; uintptr_t stack = tf->tf_regs.reg_r[LOONGARCH_REG_SP]; int cur_pid=current->pid; pipewrite(pipe_enty,"abcde",4); return 0; } 输入为“abcde”,长度为4。 因此输出结果应该如下,即abcd kernel_execve: pid = 4, name = "sh". user sh is running!!! $ size 4 size 4 abcd 特别说明 1、你必须要完成第1关的任务,确保pipealloc()函数完善后,才能进行本关卡的实验步骤。 2、有可能因为文件上传导致的Makefile文件时间戳错误,造成编译陷入死循环,可以在/home/CQUCS/ucore_cqu_2024_lab5目录下执行下述命令: find . -type f |xargs -n 5 touch make clean make 实验具体步骤 请依次执行下面的命令 cd /home/CQUCS/ucore_cqu_2024_lab5/kern/process vim proc.c 使用该命令打开文件后,输入如下命令搜索关键词"LAB5": 按下/,输入LAB5,按下Enter,进入搜索模式,按N跳转到下一个匹配项。 找到上述代码填写位置,填写本关卡的代码。 按‘i’字符进入INSERT模式便可以输入代码,输入完成后,按Esc,退出编辑模式,输入冒号:,然后输入wq,代表保存并退出,最后按下Enter,完成代码修改。 完成代码编写后,进入编译路径,执行命令如下: cd /home/CQUCS/ucore_cqu_2024_lab5 make clean make qemu 如果要退出qemu,先按下Ctrl+A,松开按键,再按下X键。static int lab5_proc0(void *arg) { struct trapframe *tf =current->tf; uintptr_t stack = tf->tf_regs.reg_r[LOONGARCH_REG_SP]; int cur_pid=current->pid; pipewrite(pipe_enty,"abcde",4); return 0; } static int lab5_proc1(void *arg) { struct trapframe *tf = current->tf; uintptr_t stack = tf->tf_regs.reg_r[LOONGARCH_REG_SP]; int cur_pid=current->pid; piperead(pipe_enty,4); return 0; }教我完成实验
12-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值