Operating system 内核开发中使用的堆栈大小

Operating system 内核开发中使用的堆栈大小,operating-system,stack,size,kernel,osdev,Operating System,Stack,Size,Kernel,Osdev,我正在开发一个操作系统,而不是编写内核,我正在设计内核。这个操作系统的目标是x86体系结构,我的目标是现代计算机。所需RAM的估计数量为256Mb或更多 使每个线程的堆栈在系统上运行的合适大小是什么?我是否应该尝试将系统设计为在达到最大长度时可以自动扩展堆栈 我想如果我没记错的话,RAM中的一个页面是4k或4096字节,这对我来说似乎并不多。我可以肯定地看到,我希望RAM中同时有1000多个整数,特别是在使用大量递归时。现在,真正的解决方案是让程序通过使用malloc来实现这一点,并管理自己的内

我正在开发一个操作系统,而不是编写内核,我正在设计内核。这个操作系统的目标是x86体系结构,我的目标是现代计算机。所需RAM的估计数量为256Mb或更多

使每个线程的堆栈在系统上运行的合适大小是什么?我是否应该尝试将系统设计为在达到最大长度时可以自动扩展堆栈

我想如果我没记错的话,RAM中的一个页面是4k或4096字节,这对我来说似乎并不多。我可以肯定地看到,我希望RAM中同时有1000多个整数,特别是在使用大量递归时。现在,真正的解决方案是让程序通过使用
malloc
来实现这一点,并管理自己的内存资源,但实际上我想知道用户对此的看法

4k是否足够容纳一堆现代计算机程序?堆栈应该比这个大吗?堆栈是否应自动扩展以适应任何类型的大小?从实际开发人员的角度和安全性的角度来看,我对此都感兴趣

4k对于堆栈来说太大了吗?考虑正常程序执行,特别是从C++类的角度来看,我注意到,良好的源代码倾向于<代码> MalC/Cux/<代码>创建类时需要的数据,以最小化函数调用中抛出的数据。
我甚至还没有了解处理器缓存的大小。理想情况下,我认为堆栈将驻留在缓存中以加快速度,我不确定是否需要实现这一点,或者处理器是否可以为我处理它。我只是打算用普通的无聊的旧RAM进行测试。我不能决定。选项是什么?

为什么不将堆栈大小设置为可配置项,或者与程序一起存储,或者在一个进程创建另一个进程时指定

您可以通过多种方式配置此功能


有一条准则规定了“0、1或n”,这意味着您应该允许对象的0、1或任意数量(受内存等其他约束的限制)-这也适用于对象的大小。

堆栈大小取决于线程正在执行的操作。我的忠告是:

  • 在线程创建时将堆栈大小设置为参数(不同的线程将执行不同的操作,因此需要不同的堆栈大小)
  • 为那些不想麻烦指定堆栈大小的人提供一个合理的默认值(4K吸引了我的控制狂,因为它会导致堆栈浪费,呃,非常快地获得信号)
  • 考虑如何检测和处理堆栈溢出。检测可能很棘手。您可以将保护页(空)放在堆栈的末尾,这通常会起作用。但是你依靠的是坏线的行为,而不是越过护城河,开始污染远处的东西。通常情况下,这不会发生……但是,这就是让真正难对付的虫子变得难对付的原因。严密的机制包括黑客攻击编译器以生成堆栈检查代码。至于处理堆栈溢出,您将需要一个专用的堆栈,在其他地方,有问题的线程(或者它的守护天使,不管你决定是谁——毕竟,你是操作系统设计者)将在其上运行
  • 我强烈建议用一种独特的模式标记堆栈的末端,这样当线程在末端运行时(它们总是这样),您至少可以在验尸时看到确实有东西从堆栈中运行。一页牛肉或类似的东西很方便

顺便说一句,x86页面大小通常为4k,但不一定是这样。您可以选择64k或更大的尺寸。使用较大页面的通常原因是为了避免TLB未命中。同样,我会将它作为一个内核配置或运行时参数。

我会投入我的两分钱,让事情顺利进行:

  • 我不确定什么是“典型”堆栈大小。我猜每个线程可能有8KB,如果一个线程超过这个数量,就抛出一个异常。但是,根据,Windows的默认保留堆栈大小为每个线程1MB,但不会一次提交所有文件(页面会根据需要提交)。此外,您可以在编译时使用编译器指令为给定的EXE请求不同的堆栈大小。不确定Linux是做什么的,但我看到了对4KB堆栈的引用(尽管我认为这可以在编译内核时更改,我不确定默认堆栈大小是多少…)

  • 这与第一点有关。您可能希望对每个线程可以获得的堆栈数量有一个固定的限制。因此,您可能不希望每次线程超过其当前堆栈空间时自动分配更多的堆栈空间,因为陷入无限递归的错误程序将耗尽所有可用内存


如果您使用的是虚拟内存,那么一定要使堆栈可扩展。强制静态分配堆栈大小的线程(如Qthreads和Windows光纤)在用户级线程(如Qthreads和Windows光纤)中很常见。难以使用,容易崩溃。我认为,所有现代操作系统都会动态地增加堆栈,通常是在当前堆栈指针下有一两个写保护的保护页。然后,写入内容会告诉操作系统堆栈已超出其分配的空间,然后在该空间下方分配一个新的保护页,并使命中的页面可写。只要没有一个函数分配超过一页的数据,这就可以正常工作。或者可以使用两个或四个保护页来允许更大的堆栈帧

如果您想要一种控制堆栈大小的方法,并且您的目标是一个真正受控且高效的环境,但不关心以与Linux等相同的方式进行编程,那么请选择单次执行模型,在该模型中,每次启动相关事件时都会启动任务
./arch/cris/include/asm/processor.h:
#define KERNEL_STACK_SIZE PAGE_SIZE

./arch/ia64/include/asm/ptrace.h:
# define KERNEL_STACK_SIZE_ORDER        3
# define KERNEL_STACK_SIZE_ORDER        2
# define KERNEL_STACK_SIZE_ORDER        1
# define KERNEL_STACK_SIZE_ORDER        0
#define IA64_STK_OFFSET         ((1 << KERNEL_STACK_SIZE_ORDER)*PAGE_SIZE)
#define KERNEL_STACK_SIZE       IA64_STK_OFFSET

./arch/ia64/include/asm/mca.h:
    u64 mca_stack[KERNEL_STACK_SIZE/8];
    u64 init_stack[KERNEL_STACK_SIZE/8];

./arch/ia64/include/asm/thread_info.h:
#define THREAD_SIZE         KERNEL_STACK_SIZE

./arch/ia64/include/asm/mca_asm.h:
#define MCA_PT_REGS_OFFSET      ALIGN16(KERNEL_STACK_SIZE-IA64_PT_REGS_SIZE)

./arch/parisc/include/asm/processor.h:
#define KERNEL_STACK_SIZE   (4*PAGE_SIZE)

./arch/xtensa/include/asm/ptrace.h:
#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)

./arch/microblaze/include/asm/processor.h:
# define KERNEL_STACK_SIZE  0x2000