如何为单字符 i/o 定义 getc 和 putc 函数,并提供适当的 i/o 操作缓冲 MIPS
Posted
技术标签:
【中文标题】如何为单字符 i/o 定义 getc 和 putc 函数,并提供适当的 i/o 操作缓冲 MIPS【英文标题】:How to define getc and putc functions for single character i/o, and provide proper buffering of i/o operations MIPS 【发布时间】:2021-07-30 13:30:19 【问题描述】:(MIPS) 如何为单字符 i/o 定义 getc 和 putc 函数,提供适当的缓冲 strong> 具有 512 字节缓冲区的输入和输入操作。 -火星4.5
【问题讨论】:
您必须分享您正在使用的系统或模拟器。 我在 MARS 4.5 中编写程序集 您是否要像int getc(FILE *stream);
一样提供FILE
类型?是的,这意味着您可能还需要fopen
/fclose
才能获得FILE *
。
缓冲部分相当简单——只是编程的问题,以及缓冲区的一些数据空间。问题是你打算如何完成 C 的 stdio 的实现?
我要写结果。但它需要提供适当的缓冲。不必一次打印出每个字符。
【参考方案1】:
好的,您实际上并不需要getc
/putc
,只需要一些执行缓冲 I/O 的函数和在某些情况下(例如退出程序)刷新 I/O 的操作。
(目前假设此缓冲不会用于控制台 I/O,即仅文件 I/O — 控制台 I/O 是交互式的,并且在使用 getc
时需要 putc
缓冲区刷新。进一步为简单起见,您只希望能够一次写入一个文件,一次读取一个文件,尽管混合 put/get ok。)
提供两个全局缓冲区,一个用于putc
,一个用于getc
。与每个缓冲区相关联的还有一个全局变量end
,它可以是一个计数或指针,以及一个值max
,它可以是编译时间常数或变量,它指示缓冲区大小。此外,putc
和getc
中的每一个都是文件描述符变量。 (对于max
的概念,Getc 需要一个真正的变量。)
putc
函数只接受一个参数,即要放置的字符;它应该将字符输入其缓冲区并增加相关联的end
— 如果end
达到max
,则使用带有参数 putc 文件描述符(全局)、putc 缓冲区(全局) 和 putc max (缓冲区大小)。您选择如何处理错误(使用消息退出程序(可能更简单),或者将错误返回给调用者?)。然后在返回调用者之前将end
重置为开头,b/c缓冲区现在是空的。
getc
函数不接受任何参数并返回一个字符或 EOF 指示符,如果缓冲区不为空,则从缓冲区中获取字符以返回,并推进 end
位置。返回之前,如果达到max
,则重置到开头。
但是,如果缓冲区为空(即end
位于开头),则使用系统调用#14 使用 getc 文件描述符、getc 缓冲区和 getc 缓冲区大小进行读取。如果该读取调用出错,则再次调用是否将错误打印到控制台并退出程序,或将错误代码返回给用户(前者可能更简单)。如果它返回 0,这意味着 EOF,所以将它(可能是 -1)返回给调用者而不是一个字符。
如果它得到一个非零字符数,则设置max
该字符数,并将字符加载到end
位置(如果您在这里,则在开头)以返回并增加end
的位置。如果end
的位置是max
,则在返回之前将其重置为开头。
初始化:客户端消费者需要将文件描述符放入getc
和putc
的全局文件描述符中,以便它们与其他全局变量一起使用。
您还需要提供flush
类型的调用,main
或其他调用者应将其用作终止程序之前的最终操作。此刷新操作将使用系统调用 #15 来写入缓冲区中当前有许多字符(如果超过 0,并将指示器重置为空缓冲区)。
客户端还应该关闭 getc/putc 之外的文件,也许还应该清除文件描述符。 (您可以考虑提供执行这些操作的退出调用。)
【讨论】:
以上是关于如何为单字符 i/o 定义 getc 和 putc 函数,并提供适当的 i/o 操作缓冲 MIPS的主要内容,如果未能解决你的问题,请参考以下文章
getc_unlocked,putc_unlocked,getchar_unlocked,putchar_unlocked