裸骨OS内核编程

时间:2015-03-06 20:08:45

标签: c linux assembly operating-system kernel

我最近开始对操作系统的主题感兴趣。我有几件事情在影响我的想法,但我决定分开问题。

让我们假设我们正在为市场上出现的新指令集架构设计内核。没有C运行时库,也没有任何东西。只有该ISA的兼容编译器。

据推测,这意味着内核程序员可用的唯一C构造只是基本赋值运算符,按位运算符和循环。这是对的吗?

如果是这样,主存储器I / O和进程调度等更复杂的事情如何在最低级别实现?它们只能用纯装配实现吗?

对于用C语言编写的内核(例如Linux)来说,这意味着什么。内核的某些部分本身是用汇编语言编写的吗?

3 个答案:

答案 0 :(得分:7)

  

据推测,这意味着内核程序员可用的唯一C构造只是基本赋值运算符,按位运算符和循环。这是对的吗?

几乎所有C语言功能仍然可以在你的内核中运行而不需要任何特定的运行时支持,你的C编译器将能够将它们转换为可以在内核模式下运行的汇编程序,就像在普通用户中一样 - 模式程序。

但是,如果标准C库等库不可用,则必须编写自己的实现。特别是,这意味着在您自己实施之前不会mallocfree

  

如果是这样,主存储器I / O和进程调度等更复杂的事情如何在最低级别实现?它们只能用纯装配实现吗?

Memory I/O is something much more low level由计算机上的CPU,BIOS和各种其他硬件处理。谢天谢地,操作系统不必为此烦恼(除了一些例外,例如某些地址被保留,以及一些内存管理功能)。

流程调度是一种在大多数架构上的机器代码级别并不存在的概念。 x86确实有a concept of tasks和硬件任务切换但nobody uses it。这是操作系统根据需要设置的抽象,您必须自己实现它,或者如果您不想花费精力,您可以决定使用单任务操作系统,它仍然有效。

  

对于用C语言编写的内核(例如linux)来说,这意味着什么。内核的某些部分本身是用汇编语言编写的吗?

内核的某些部分将严重依赖于体系结构,必须使用ASM编写。例如on x86 switching between modes(例如,运行16位代码,或作为引导过程的一部分)或中断处理只能通过一些受保护的ASM指令来完成。您选择的体系结构的参考手册,例如x86的Intel® 64 and IA-32 Architectures Software Developer’s Manual是第一个查找这些细节的地方。

但是C是一种可移植的语言,它不需要这种低级别的体系结构特定的概念(尽管理论上你可以从带有编译器内在函数和内联ASM的.c文件中做所有事情)。在汇编程序中抽象出来更有用,并在一个干净的界面上构建你的C代码,如果你想将操作系统移植到另一个架构,你可以维护它。

如果您对此主题感兴趣,我强烈建议您访问the OS Development Wiki,它是有关操作系统的重要信息来源,您会找到许多与您有共同兴趣的爱好者。

答案 1 :(得分:2)

关于汇编程序中唯一需要编码的事情是:

  • 上下文切换(将一个抽象过程的机器状态换成另一个)
  • 访问设备寄存器(如果设备是内存映射的,您甚至不需要这样做)
  • 进入和退出中断处理程序(这是一种上下文切换)

  • 也许是引导加载程序

否则你应该可以用C代码。

如果您希望看到这项工作做得非常好,那么您应该查看可以追溯到60年代中期的Multics操作系统,支持大规模信息服务(多CPU,虚拟内存,... )。这几乎完全用PL / 1(类C语言)编码,只有非常小的位用霍尼韦尔处理器的原生汇编语言编码,支持Multics。关于Multics的Organick书在展示Multics如何工作以及它的大部分清洁方面都非常重要。 (我们得到了“太监”)。

有些地方无论如何都需要在汇编程序中进行编码。无论编译器代码生成器的质量如何,您都能够在汇编程序中比编译器更好地手动编写在时间关键区域中发生的某些例程。我希望这件事的地方:调度程序,系统调用进入和退出。其他地方仅作为测量指示。 (在较旧的,体积更小的系统中,人们倾向于使用大量的汇编程序来编写操作系统,但这对于节省空间和执行效率一样多,C编译器也不是那么好。)

答案 2 :(得分:1)

我想知道“面向市场”的新架构如何不具备某种类型的操作系统。

设备驱动程序 - 有人必须为此编写代码,可能是一个用于BIOS的驱动程序,另一个用于操作系统。内存映射I / O可能会因硬件而变得复杂,例如带有一组描述符的控制器,每个描述符包含一个物理地址和长度。如果操作系统支持虚拟内存,则必须“锁定”该内存并获取物理地址以便对控制器进行编程。这是拥有一组描述符的一个原因,因此单个内存映射I / O可以处理已映射到连续虚拟地址空间的分散物理页面。

汇编代码 - 这里的其他注释已经注意到将需要一些汇编(上下文切换,中断处理程序(可以调用C函数,因此大多数代码可以在C中)。)