内核堆栈和用户堆栈有什么区别?为什么使用内核栈?如果在 ISR 中声明局部变量,它将存储在哪里?每个进程都有自己的内核堆栈吗?那么进程如何在这两个堆栈之间进行协调呢?
- 内核堆栈和用户堆栈有什么区别?
简而言之,除了使用内存中的不同位置(因此堆栈指针寄存器的值不同)以及通常不同的内存访问保护之外,什么都没有。 IE。当在用户模式下执行时,即使映射,内核内存(其中一部分是内核堆栈)也将不可访问。反之亦然,无需内核代码明确请求(在 Linux 中,通过诸如copy_from_user()
),用户内存(包括用户堆栈)通常不能直接访问。
- 为什么使用[单独的]内核堆栈?
特权和安全的分离。其一,用户空间程序可以将其堆栈(指针)设置为任何他们想要的,并且通常没有体系结构要求,甚至没有有效的堆栈。因此内核不能trust用户空间堆栈指针有效且不可用,因此需要一组在其自己的控制下。不同的CPU架构以不同的方式实现这一点;当特权模式切换发生时,x86 CPU 会自动切换堆栈指针,并且用于不同特权级别的值是可以通过特权代码(即仅内核)进行配置的。
- 如果在 ISR 中声明局部变量,它将存储在哪里?
在内核堆栈上。内核(即 Linux 内核)确实not将 ISR 直接挂接到 x86 架构的中断门而是将中断调度委托给通用内核中断进入/退出机制,该机制在调用注册的处理程序之前保存中断前寄存器状态。 CPU 本身在分派中断时可能会执行特权和/或堆栈切换,并且这是由内核使用/设置的,以便公共中断入口代码已经可以依赖于存在的内核堆栈。
也就是说,执行内核代码时发生的中断将简单地(继续)使用此时的内核堆栈。如果中断处理程序具有深层嵌套的调用路径,这可能会导致堆栈溢出(如果深层内核调用路径被中断并且处理程序导致另一个深层路径;在 Linux 中,文件系统/软件 RAID 代码被具有 iptables 活动状态的网络代码中断)已知会在未调整的旧内核中触发此类...解决方案是增加此类工作负载的内核堆栈大小)。
- 每个进程都有自己的内核堆栈吗?
不仅仅是每个流程 - 每个thread有自己的内核堆栈(事实上,也有自己的用户堆栈)。请记住,进程和线程(对于 Linux)之间的唯一区别是多个线程可以共享地址空间(形成进程)。
- 进程如何在这两个堆栈之间进行协调?
一点也不——不需要。调度(如何/何时运行不同的线程,如何保存和恢复它们的状态)是操作系统的任务,进程不需要关心这个。创建线程时(每个进程必须至少有一个线程),内核为它们创建内核堆栈,而用户空间堆栈则由用于创建线程的机制显式创建/提供(例如makecontext()
or pthread_create()
允许调用者指定用于“子”线程堆栈的内存区域),或继承(通过访问内存克隆,通常称为“写入时复制”/COW,在创建新进程时)。
也就是说,这个过程can影响其线程的调度和/或影响context(状态,其中是线程的堆栈指针)。有多种方法可以实现这一点:UNIX 信号、setcontext()
, pthread_yield()
/ pthread_cancel()
,... - 但这有点偏离原来的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)