自定义操作系统中的一般保护

时间:2011-10-20 13:42:40

标签: assembly operating-system x86 x86-64

我打算为英特尔64位架构编写自己的操作系统,我需要实现一般保护机制。我不会使用虚拟内存或分页,而是使用物理寻址。我还不知道如何实现它,但我有一个大致的想法,它是这样的:

  1. 在启动时,内核将被加载,并假设它将启动第一个名为“filemanager”的用户空进程,该进程将一些数据保存到另一个进程收到的某些信号上。
  2. filemanager将包含代码段,堆栈段和数据段。
  3. 在正常操作期间,内核将启动另一个进程,这将从可用的物理内存堆中获取内存,管理内核负责的内容。
  4. 让我们假设,'filemanager'进程需要获得更多ram,因为它的数据段已满。它向内核发送一个系统调用以请求另一个数据段。内核为它提供了所请求的内存块,它位于物理上不同的位置,并且与第一段无关。
  5. 现在问题是,应用程序('filemanager')将如何处理2个段?因为据我所知,英特尔实施的通用保护机制只能检查存储在“DS”中的当前段的限制。但是在filemanager的情况下,我们现在有2个细分市场。我是否必须在应用程序内手动从一个段切换到另一个段?编写像这样的应用程序会很痛苦 因为你必须写这样的东西:

        __asm('set DS register to the address and length of segment 1');
        for (i=0;i<size_of_segment1;i++) {
            segment1_data[i]= some_processing();
        }
        __asm('set DS register to the address and length of segment 2');
        for (i=0;i<size_of_segment2;i++) {
            segment2_data[i]= some_processing();
        }
    

    这仅适用于2个细分市场,但想象一下,应用程序必须向内核询问1000个或更多数据段,如何实现常规保护机制,以便为开发人员快速轻松地编程?实现此目的的一种方法是修改GCC,并且必须插入汇编代码以在访问每个数据段之前将相应的数据段加载到DS寄存器中,但这看起来很多工作。还有其他方法吗?

    ...继续 5.共享内存。让我们说另一个进程'编辑'需要通过'filemanager'进程保存一些数据。操作系统必须提供共享内存机制。 “编辑器”进程将请求内核添加“filemanager”进程的数据段。 'filemanager'将确认请求,新段将被添加到编辑器的数据段列表中,以便它可以合法地写入它。同样的问题是,如何在“编辑器”内的多个段之间切换,对应用程序是透明的,对整个系统是否安全?

    注意:我不会在我的操作系统中使用分页,所有内存寻址都是物理的,并且它将处于64模式。

2 个答案:

答案 0 :(得分:2)

如果您处于64位模式,则根本没有段寄存器:CS,DS ...的内容将被忽略。地址是“平坦”地址空间中的64位值。段寄存器用于16位和32位模式,尽管大多数32位操作系统将所有段设置为从地址0开始并跨越4 GB,因此它们可能永远忘记它们。如果你使用段寄存器(这样应用程序代码可能会使用几个“段”),那么在C级别,C编译器必须知道它们,并且“指针”将包括段和偏移值。设置段寄存器很昂贵,因此如果您可以不使用段,性能会更好。这解释了为什么像Linux或Windows这样的32位操作系统不使用段,相应地,CPU供应商已经适应并简单地省略了64位模式下的段支持。

真正的问题是:你想在应用程序之间保护内存吗?内存保护是关于阻止进程读取或写入不应该读/写的内存,即另一个进程或内核使用的内存。如果应用程序员永远不会编写带有错误的代码(mmh ......这看起来多么合理?)如果应用程序是用包含禁止无效内存访问的系统检查的语言编写的,则可以不使用内存保护内存(例如Java)(JNode项目是关于Java中的操作系统,但我不知道它是否还活着)。要获得内存保护,请使用MMU。 MMU通过“页面”工作:地址空间被分成固定大小的页面(x86上每个4kB),操作系统在RAM中安装表格,告诉MMU每个页面的物理位置。分页,基于磁盘的虚拟内存...使用MMU。但您也可以使用MMU“仅”进行内存保护(您可以将其设置为使每个页面出现在等于其物理地址的虚拟地址,或者如果当前不访问该页面则标记为“不存在”允许的)。

根本不使用MMU可以在某些非常特殊的情况下提升性能(我知道有人正在进行筛选,作为面向加密的大型计算工作的一部分:筛选几乎是100%随机存储的内存访问1 GB阵列; MMU意味着三次缓存未命中而不是每次访问一次,因此没有MMU就会使整个事情快三倍 - 但这确实是一个边缘情况)。另一方面,MMU使应用程序开发人员的工作更轻松,特别是因为它允许每个应用程序都有自己的规范化地址空间(例如,您可以提前编译和链接 C代码)。

答案 1 :(得分:0)

从另一个角度来看,比如说想要访问你的记忆的C程序员会怎样? Kernel.AllocateMemory返回什么?它不能返回64位值,因为它不足以表示段和偏移量(实际上,x64机器现在可以访问少于2 ^ 64字节的内存,因此您可以在某些段中存储段号未使用的位,但我认为你不想这样做。)

听起来你正在寻找的是一个“远指针”(来自过去的爆炸 - 见例如http://www.daniweb.com/software-development/c/threads/345287)。

如果您不想手动更改段,那么我看不出如何逃避支持远指针的编译器修改。请注意,如果您只有两个段,那么您可以使用DS和ES来寻址数据,但即使这样也需要不同的汇编代码,具体取决于您要使用的段。有人必须决定生成这个代码,它将是你或编译器。