linux - 内核栈和用户空间栈

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

最佳答案

  1. What's the difference between kernel stack and user stack ?

简而言之,除了使用内存中的不同位置(因此堆栈指针寄存器的值不同)以及通常不同的内存访问保护之外,什么都没有。 IE。在用户模式下执行时,即使映射了内核内存(其中一部分是内核堆栈)也将无法访问。反之亦然,如果内核代码没有明确请求(在 Linux 中,通过 copy_from_user() 等函数),用户内存(包括用户堆栈)通常不能直接访问。

  1. Why is [ a separate ] kernel stack used ?

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

  1. If a local variable is declared in an ISR, where will it be stored ?

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

  1. Does each process have its own kernel stack ?

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

  1. How does the process coordinate between both these stacks ?

根本不需要 - 它不需要。调度(如何/何时运行不同的线程,如何保存和恢复它们的状态)是操作系统的任务,进程不需要关心这一点。当线程被创建(并且每个进程必须至少有一个线程)时,内核为它们创建内核堆栈,而用户空间堆栈要么由用于创建线程的任何机制显式创建/提供(像 makecontext 这样的函数()pthread_create() 允许调用者指定要用于“子”线程堆栈的内存区域)或继承(通过访问内存克隆,通常称为“写时复制”/COW,创建新进程时)。
也就是说,进程可以影响其线程的调度和/或影响上下文(状态,其中是线程的堆栈指针)。有多种方法:UNIX 信号、setcontext()pthread_yield()/pthread_cancel()、... - 但这是与原始问题有点离题。

https://stackoverflow.com/questions/12911841/

相关文章:

python - 如何让 python 的 pprint 返回一个字符串而不是打印?

linux - 如何使用 strace 跟踪子进程?

mysql - MySQL 服务器和 MySQL 客户端有什么区别

linux - gettimeofday() 是否保证为微秒级分辨率?

python - 如何在 Windows 上运行多个 Python 版本

python - 使用 IPython 逐步调试

python - 使用 argparse 需要两个参数之一

python - 在 Python 字符串中的最后一个分隔符上拆分?

linux - 如何通过将其内存存储到磁盘并稍后恢复它来在 Linux 中 "hibernate"进

linux - 使用 unix 命令 "watch"的颜色?