内核堆栈和用户堆栈之间有什么区别?为什么要使用内核堆栈?如果在ISR中声明了局部变量,那么它将被存储在哪里?每个进程都有自己的内核堆栈吗?那么这个过程如何在这两个堆栈之间进行协调?
答案 0 :(得分:161)
- 内核堆栈和用户堆栈有什么区别?
醇>
简而言之,没有 - 除了在内存中使用不同的位置(因此堆栈指针寄存器的值不同),以及通常不同的内存访问保护。即在用户模式下执行时,内核内存(其中一部分是内核堆栈)即使映射也无法访问。反之亦然,没有明确地被内核代码请求(在Linux中,通过像copy_from_user()
这样的函数),用户内存(包括用户堆栈)通常不能直接访问。
- 为什么使用[单独的]内核堆栈?
醇>
分离权限和安全性。例如,用户空间程序可以使它们的堆栈(指针)成为他们想要的任何东西,并且通常没有架构要求甚至没有架构要求。因此,内核不能信任用户空间栈指针有效也不可用,因此需要一组在其自己的控制之下。不同的CPU架构以不同的方式实现这一点;当特权模式切换发生时,x86 CPU会自动切换堆栈指针,并且可以配置用于不同权限级别的值 - 通过特权代码(即只有内核)。
- 如果在ISR中声明了局部变量,它将存储在哪里?
醇>
在内核堆栈上。内核(Linux内核,即)不将ISR直接挂钩到x86架构的中断门,而是将中断调度委托给公共内核中断入口/出口机制,在调用注册的处理程序之前保存预中断寄存器状态。调度中断时CPU本身可能会执行权限和/或堆栈切换,这由内核使用/设置,以便公共中断条目代码可以依赖于存在的内核堆栈。
也就是说,执行内核代码时发生的中断将在那时简单地(继续)使用内核堆栈。如果中断处理程序具有深度嵌套的调用路径,则会导致堆栈溢出(如果深度内核调用路径中断且处理程序导致另一个深度路径;在Linux中,文件系统/软件RAID代码被iptables活动的网络代码中断)已知在未经验证的旧内核中触发此类内容...解决方案是增加此类工作负载的内核堆栈大小。)
- 每个进程都有自己的内核堆栈吗?
醇>
不仅每个进程 - 每个线程都有自己的内核堆栈(事实上,它也是自己的用户堆栈)。请记住,进程和线程(对Linux)之间的唯一区别是多个线程可以共享一个地址空间(形成一个进程)。
- 这两个堆栈之间的流程如何协调?
醇>
完全没有 - 它不需要。调度(如何/何时运行不同的线程,如何保存和恢复其状态)是操作系统的任务和过程不需要关心它。在创建线程(并且每个进程必须至少有一个线程)时,内核为它们创建内核堆栈,而用户空间堆栈由用于创建线程的任何机制显式创建/提供(像makecontext()
这样的函数或pthread_create()
允许调用者指定一个用于“子”线程堆栈的内存区域,或者继承(通过访问时内存克隆,通常称为“写入时复制”/ COW,创建新的时)过程)。
也就是说,进程可以影响其线程的调度和/或影响上下文(状态,其中就是线程的堆栈指针)。有多种方法可以解决这个问题:UNIX信号,setcontext()
,pthread_yield()
/ pthread_cancel()
,...... - 但这与原始问题有点不同。
答案 1 :(得分:15)
我的回答是从我的其他SO问题中收集的。
What's the difference between kernel stack and user stack?
作为内核程序员,您知道应该将内核限制在错误的用户程序之外。假设你为内核和内核保持相同的堆栈。用户空间,然后用户应用程序中的简单段错误会导致内核崩溃并需要重新启动。
每个CPU有一个“内核堆栈”,如ISR堆栈,每个进程有一个“内核堆栈”。每个进程都有一个“用户堆栈”,尽管每个线程都有自己的堆栈,包括用户和内核线程。
http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html
Why kernel stack is used?
因此,当我们处于内核模式时,堆栈类型的机制是处理函数调用,类似于用户空间的局部变量所必需的。
http://www.kernel.org/doc/Documentation/x86/kernel-stacks
If a local variable is declared in an ISR, where it will be stored?
它将存储在ISR堆栈(IRQSTACKSIZE)中。仅当硬件支持时,ISR才在单独的中断堆栈上运行。否则,ISR堆栈帧被推入中断线程的堆栈。
用户空间不知道,并且坦率地不关心中断是在当前进程的内核堆栈还是单独的ISR堆栈中提供。由于每个CPU都有中断,因此ISR堆栈必须是每个CPU。
Does each process has its own kernel stack ?
是。每个进程都有自己的内核堆栈。
Then how the process coordinates between both these stacks?
@ FrankH的答案看起来很棒。
答案 2 :(得分:3)
- 内核堆栈和用户堆栈有什么区别
参考Robert Love的Linux Kernel Development,主要区别在于大小:
用户空间可以在堆栈上静态分配许多变量,包括 巨大的结构和上千个元素的数组。
此行为是合法的,因为用户空间具有 可以动态增长的大堆栈。
内核堆栈既不大也不动态。它很小而且尺寸固定。
内核堆栈的确切大小因架构而异。
在x86上,堆栈大小可在以下位置配置 编译时,可以为4KB或8KB。
从历史上看,内核堆栈是两个页面, 这通常意味着在32位体系结构上为8KB,在64位体系结构上为16KB。 大小是固定且绝对的。
每个进程都有自己的堆栈。
此外,内核堆栈还包含指向thread_info结构的指针,该结构保存有关线程的信息。