我正在为C中的程序编写一个小内核.
这不是(目前)OS内核,它只是我在不依赖外部源(即stdio.h)的情况下跟踪程序中的输入和输出的一种方式.你可能会问我为什么要这样做; 它只是让我知道这是如何工作的,所以我有更多,更多(最终目标是完全)控制程序流程.
我想知道是否有人知道C中的输入和输出的一些教程(使用内联asm?)而不依赖于任何其他代码.
裸金属和stdio之间有很多空间.您已经说过,您不是在编写操作系统内核,而是在运行操作系统下运行.
直接在没有操作系统的硬件上运行,您仍然希望将所有I/O操作封装在模块中,即使您没有正式定义所有I/O模块的设备驱动程序接口和框架.这非常依赖于体系结构,使您有责任了解与您可能使用的每个I/O设备交互的所有细节.对于某些设备,这很快就会成为一项巨大的开发工作.这对于嵌入式系统来说不是问题,但是以这种方式在商业硬件上运行既不容易也不推荐.
在OS中运行,您可能无法(并且不应该想)获得对实际硬件寄存器和中断的访问权限.如果您正在开发自定义I/O设备,最佳做法是使其符合现有标准,以便您尽可能少地使用低级自定义软件.这就是为什么你会看到很多自定义用户界面小工具通过USB连接并将自己标识为HID(人机接口设备)的原因.作为HID,现有USB驱动程序负责物理层,OS提供的HID驱动程序负责逻辑接口,为应用程序提供非常简单的高级访问API.
操作系统的关键角色之一是在所有设备上提供一致的I/O API.一般来说,采用的形式open()
,close()
,read()
,write()
,和ioctl()
功能(名称各不相同,但某种形式的至少前四会一直存在).然而,OS层非常原始.通常,OS调用在没有太多处理的情况下被转发到设备驱动程序,然后设备驱动程序将数据转发到设备上.通常,操作系统低级别调用会阻止调用方直到它们完成,并且通常它们对有意义的缓冲区大小有限制.例如,对磁盘设备的原始访问通常需要一次用于整数个磁盘块.
不要忘记文件系统和网络协议之类的东西......所有这些都通过操作系统中的封装变得更加可靠和兼容.
即使可以接受呼叫read()
和write()
单个字符,这通常也不是最佳性能.操作系统调用相对昂贵,如果您可以在一次调用中读取多个字符,那么您的性能可能会提升.
这是C的stdio库的起源,以及其他环境中的各种其他缓冲库.stdio库提供了一个缓冲层,可以将C代码与底层硬件的块大小隔离开来.即使在完全由本土操作系统完全控制所有设备的情况下,像C stdio这样的东西仍然很有价值.
编写自己的stdio更换是非常宝贵的锻炼,即使你没有在生产代码中使用它,是一个我会推荐给任何人想要了解真正的推移之间printf()
以及scanf()
与终端或文件.
一个宝贵的资源是PJ Plauger的The Standard C Library一书.在其中,作者提出了ANSI标准中指定的完整C运行时库的实现.他对他所做出的具体实施选择的讨论对于这个问题的背景是有价值的,并且对于为什么某些标准库特征被指定的讨论也是有趣的.
这种事情是非常具体的架构.简而言之,您的I/O设备将引发CPU的硬件中断.CPU将调用与中断相关的代码,该代码将适当地处理它; 对于输入设备,它将获取设备可用的数据,对于输出设备,中断通常意味着设备已准备好发送下一个设备.
旧的8088/8086 CPU架构是一个很好的简单的地方开始了解这个.通常,BIOS将处理硬件中断的位置,但始终可以编写自己的中断.;)