小编典典

内核堆栈和用户空间堆栈

linux

内核堆栈和用户堆栈有什么区别?为什么要使用内核堆栈?如果在ISR中声明了局部变量,它将存储在哪里?每个进程都有自己的内核堆栈吗?那么,进程如何在这两个堆栈之间进行协调?


阅读 621

收藏
2020-06-02

共1个答案

小编典典

  1. 内核堆栈和用户堆栈有什么区别?

简而言之,除了在内存中使用不同的位置(并因此为堆栈指针寄存器使用不同的值)之外,什么也没有,而且通常使用不同的内存访问保护。也就是说,在用户模式下执行时,即使映射了内核内存(其中一部分是内核堆栈)也将不可访问。反之亦然,在没有内核代码明确要求的情况下(在Linux中,通过诸如之类的功能copy_from_user()),通常无法直接访问用户内存(包括用户堆栈)。

  1. 为什么使用[单独的]内核堆栈?

特权与安全性分离。首先,用户空间程序可以使它们的堆栈(指针)成为他们想要的任何东西,并且通常没有架构上的要求就可以拥有一个有效的堆栈。因此,内核不能
信任 用户空间堆栈指针是有效的也不可用,因此将需要一组在其自己的控制之下。不同的CPU架构以不同的方式实现此目的。当发生特权模式切换时,x86
CPU会自动切换堆栈指针,并且可以通过特权代码(即仅内核)配置用于不同特权级别的值。

  1. 如果在ISR中声明了局部变量,它将存储在哪里?

在内核堆栈上。内核(即Linux内核)不会 ISR直接挂钩到x86架构的 中断门
,而是将中断分派委托给通用的内核中断进入/退出机制,该机制可以在调用注册的处理程序之前保存中断前寄存器的状态。
。调度中断时,CPU本身可能会执行特权和/或堆栈切换,并且内核会使用/设置该切换,以便公用中断入口代码已经可以依赖存在的内核堆栈。
就是说,在执行内核代码时发生的中断将简单地(继续)在那时使用内核堆栈。如果中断处理程序具有深层嵌套的调用路径,则可能导致堆栈溢出(如果深层内核调用路径被中断,并且处理程序导致了另一条深层路径;在Linux中,文件系统/软件RAID代码被iptables处于活动状态的网络代码中断了)已知会在未调整的较旧内核中触发此类问题……解决方案是增加此类工作负载的内核堆栈大小)。

  1. 每个进程都有自己的内核堆栈吗?

不仅仅是每个进程-每个 线程
都有自己的内核堆栈(实际上,也有自己的用户堆栈)。请记住,进程和线程(对于Linux)之间的唯一区别是多个线程可以共享一个地址空间(形成一个进程)。

  1. 流程如何在这两个堆栈之间进行协调?

完全没有-
不需要。调度(如何/何时运行不同的线程,如何保存和恢复它们的状态)是操作系统的任务,而进程不必为此担心。创建线程时(每个进程必须至少有一个线程),内核会为它们创建内核堆栈,而用户空间堆栈则由用于创建线程的任何机制显式创建/提供(函数类似于makecontext()pthread_create()允许调用者指定要用于“子”线程堆栈的内存区域)或继承(通过按访问内存克隆,在创建新进程时通常称为“写时复制”
/ COW)。
那就是 (状态,其中包括线程的堆栈指针)。 这有多种方式:UNIX信号setcontext()pthread_yield()/
pthread_cancel(),… -但这disgressing从原来的问题有点。

2020-06-02