Answers:
- 内核堆栈和用户堆栈有什么区别?
简而言之,除了在内存中使用不同的位置(并因此为堆栈指针寄存器使用不同的值)之外,什么也没有,而且通常使用不同的内存访问保护。即在用户模式下执行时,即使映射了内核内存(其中一部分是内核堆栈)也将不可访问。反之亦然,在没有内核代码明确要求的情况下(在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()
,... -但这disgressing从原来的问题有点。
我的答案是从其他SO问题中收集的。
What's the difference between kernel stack and user stack?
作为内核程序员,您知道应该限制内核访问错误的用户程序。假设您为内核和用户空间保留了相同的堆栈,那么用户应用程序中的简单segfault会使内核崩溃并需要重新启动。
每个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的回答对我来说很好。
- 内核堆栈和用户堆栈有什么区别
参考Robert Love的Linux Kernel Development的参考,主要区别在于大小:
通过在堆栈上静态分配许多变量(包括巨大的结构和数千个元素的数组),可以摆脱用户空间的束缚。
此行为是合法的,因为用户空间具有可以动态增长的大堆栈。
内核堆栈既不大也不动态。它很小,尺寸固定。
内核堆栈的确切大小因体系结构而异。
在x86上,堆栈大小在编译时是可配置的,可以是4KB或8KB。
从历史上看,内核堆栈为两页,这通常意味着在32位体系结构上为8KB,在64位体系结构上为16KB,该大小是固定的且是绝对的。
每个进程都有自己的堆栈。
另外,内核堆栈还包含一个指向thread_info结构的指针,该结构保存有关线程的信息。