繁体   English   中英

在Linux内核中堆栈内存

[英]Stack memory inside the Linux kernel

我最近尝试想象一下如何在Linux内核中处理堆栈内存,但是无法提供任何可靠的方法。 我知道内核使用其自身的功能进行动态内存管理,但是我不知道它如何仅管理普通的C堆栈内存,因为毕竟可以用普通的C实现并用普通的GCC进行编译。 据我了解,堆栈内存分配通常在处理操作系统甚至是AVR之类时通过libc的形式来处理。 据我所知,尽管Linux内核不依赖libc?

我并不完全确定堆栈内存管理最初是如何委派给libc的,尽管它似乎是内置的语言功能。 我能想象的是,它是以某种方式进行了一般性的编译(或实现),因此可以在以后分配提供程序,也可以在编译过程中分配它。 有人可以帮我一下吗?

在链接步骤中分配了堆栈内存(整个堆栈)。

堆栈内存(通常)放置在.stack段中(无非是偏移量和长度,没有内容)。

.startup代码(通常是某些库中的汇编函数,我不确定哪个库)在已加载的代码中找到.stack节的名称,添加长度值以获取堆栈的最高地址(堆栈向下增长) )和(在其他几个操作中)设置spbp寄存器。

当操作系统运行时(IE不在“用户”模式下),它(通常)具有其自己的堆栈空间,并将其自身的值用于spbp寄存器。

“用户”模式和“特权”模式之间的切换以及寄存器值的交换是在您编写的内容与内核中的代码之间的转换中进行的。

大多数此类切换是在libc库的包装函数中处理的,结果控件通过跳转到内核例程的跳转表进行转换。

注意:其他CPU和OS在完成事情方面有不同的细节,但是结果非常相似。

堆栈可以是任何读/写存储器块。 堆栈没有什么特别的。 操作系统创建一个堆栈(即,它分配内存并将其位置分配给堆栈指针寄存器),因为启动进程需要一个,但它不管理堆栈。

在unix-land中,运行程序分为两个步骤。 首先,克隆父进程。 因此,新进程具有与父进程相同的堆栈设置。

最后,执行程序。 程序加载从可执行文件中获取所需的堆栈大小,而可执行文件又从链接器中获取信息(例如,参见ld命令的“ stack”选项)。

启动后,应用程序可以调用系统服务来分配内存页面,并使堆栈指针寄存器引用该页面。 然后成为程序堆栈。

请记住,这全部是指USER堆栈。 操作系统会针对其自己目的使用的每个进程维护一个KERNEL堆栈。

就我所知,堆栈内存分配通常以libc的形式处理……

该程序说明了libc中的任何内容都不用于堆栈内存分配:

// compile with: gcc -nostdlib nolibc.c -o nolibc
_start()
{
    int a[9999];
    *a = 0;
    asm("   mov %0,%%ebx\n\
            mov $1,%%eax\n\
            int $128" : : "r" (*a));    // _exit(*a);
}

如果超出了分配的堆栈空间,则会发生错误,并且内核的错误处理程序可以分配更多的空间,除非达到限制或使用固定大小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM