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

推荐答案

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

简而言之,除了在内存中使用不同的位置(因此堆栈指针寄存器的值不同),以及通常不同的内存访问保护之外,什么都没有.也就是说,在用户模式下执行时,内核内存(内核堆栈的一部分)即使被映射也无法访问.反之亦然,没有内核代码的明确请求(在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 ?

On the kernel stack. The kernel (Linux kernel, that is) does not hook ISRs directly to the x86 architecture's interrupt gates but instead delegates the interrupt dispatch to a common kernel interrupt entry/exit mechanism which saves pre-interrupt register state before calling the registered handler(s). The CPU itself when dispatching an interrupt might execute a privilege and/or stack switch, and this is used/set up by the kernel so that the common interrupt entry code can already rely on a kernel stack being present.
That said, interrupts that occur while executing kernel code will simply (continue to) use the kernel stack in place at that point. This can, if interrupt handlers have deeply nested call paths, lead to stack overflows (if a deep kernel call path is interrupted and the handler causes another deep path; in Linux, filesystem / software RAID code being interrupted by network code with iptables active is known to trigger such in untuned older kernels ... solution is to increase kernel stack sizes for such workloads).

  1. Does each process have its own kernel stack ?

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

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

Not at all - it doesn't need to. Scheduling (how / when different threads are being run, how their state is saved and restored) is the operating system's task and processes don't need to concern themselves with this. As threads are created (and each process must have at least one thread), the kernel creates kernel stacks for them, while user space stacks are either explicitly created/provided by whichever mechanism is used to create a thread (functions like makecontext() or pthread_create() allow the caller to specify a memory region to be used for the "child" thread's stack), or inherited (by on-access memory cloning, usually called "copy on write" / COW, when creating a new process).
That said, the process can influence scheduling of its threads and/or influence the context (state, amongst that is the thread's stack pointer). There are multiple ways for this: UNIX signals, setcontext(), pthread_yield() / pthread_cancel(), ... - but this is digressing a bit from the original question.

Linux相关问答推荐

如何告诉链接器不要在链接的共享库中查找某些符号?

为什么在已连接的设备上调用 btmgmt conn-info 返回:状态 0x02(未连接)

重新运行时避免 Linux bash 脚本中的文件重命名重复

如何使用netcat为DPDK实例提供输入?

当 skylake 有 fsgsbase 时,为什么使用 __builtin_ia32_wrfsbase64 会收到非法指令?

有没有办法定义自定义隐式 GNU Make 规则?

为什么 8 位字符串文字可以包含多字节字符,而 char 向量不能?

argv的编码是什么?

通过 Linux FrameBuffer 将像素绘制到屏幕上

Linux 上的 C++ 开发 - 我从哪里开始?

yum 可以告诉我哪些存储库提供了特定的包吗?

命令列出除 . (点)和..(点点)

如何在没有空格的情况下打印 awk?

ctrl-x 在终端中使用时会发送哪个信号?

当父进程被杀死时,使用 fork() 创建的子进程是否会自动被杀死?

Docker:您是否try 连接到没有 TLS 的启用 TLS 的守护进程?

`cd //` 中的双斜杠 // 在 Linux 中是什么意思?

Hierarchical分层 ldd(1)

将默认 Python 版本从 2.4 更改为 2.6

在linux中根据内容拆分文件