进程的用户栈和内核栈

进程在运行时拥有用户栈和内核栈,分别位于用户空间和内核空间。当进程从用户态切换到内核态时,通过保存用户栈地址到内核栈并设置堆栈指针寄存器指向内核栈完成栈的切换。反之,从内核态返回用户态则恢复用户栈地址。内核栈用于保存中断和系统调用时的数据,而用户栈处理用户态的函数调用。设置双栈是为了确保安全性并允许进程间共享内核资源。

进程的堆栈
  内核在创建进程的时候,在创建task_struct的同时,会为进程创建相应的堆栈。每个进程会有两个栈,一个用户栈,存在于用户空间,一个内核栈,存在于内核空间。当进程在用户空间运行时,cpu堆栈指针寄存器里面的内容是用户堆栈地址,使用用户栈;当进程在内核空间时,cpu堆栈指针寄存器里面的内容是内核栈空间地址,使用内核栈。

进程用户栈和内核栈的切换
  当进程因为中断或者系统调用而陷入内核态执行时,进程所使用的堆栈也要从用户栈转到内核栈。
  进程陷入内核态后,先把用户态堆栈的地址保存在内核栈之中,然后设置堆栈指针寄存器的内容为内核栈的地址,这样就完成了用户栈向内核栈的转换;当进程从内核态恢复到用户态之行时,在内核态之行的最后将保存在内核栈里面的用户栈的地址恢复到堆栈指针寄存器即可。这样就实现了内核栈和用户栈的互转。
  从内核转到用户态时,用户栈的地址是在陷入内核的时候保存在内核栈里面的,但是在陷入内核的时候,又是如何知道内核栈的地址的呢?
  关键在进程从用户态转到内核态的时候,进程的内核栈总是空的。这是因为,当进程在用户态运行时,使用的是用户栈,当进程陷入到内核态时,内核栈保存进程在内核态运行的相关信息,但是一旦进程返回到用户态后,内核栈中保存的信息无效,会全部恢复,因此每次进程从用户态陷入内核的时候得到的内核栈都是空的。所以在进程陷入内核的时候,直接把内核栈的栈顶地址给堆栈指针寄存器就可以了。

内核栈和用户栈区别

  内核创建进程,创建进程的同时创建进程控制块,创建进程自己的堆栈。一个进程有两个堆栈,用户栈和系统栈。用户堆栈的空间指向用户地址空间,内核堆栈的空间指向内核地址空间。
  有个CPU堆栈指针寄存器,进程运行的状态有用户态和内核态,当进程运行在用户态时。CPU堆栈指针寄存器指向的是用户堆栈地址,使用的是用户堆栈;当进程运行在内核态时,CPU堆栈指针寄存器指向的是内核堆栈地址,使用的是内核堆栈。

1、堆栈切换
  当系统因为系统调用(软中断)或硬件中断,CPU切换到特权工作模式,进程陷入内核态,进程使用的栈也要从用户栈转向系统栈。从用户态到内核态要两步骤,首先是将用户堆栈地址保存到内核堆栈中,然后将CPU堆栈指针寄存器指向内核堆栈。当由内核态转向用户态,步骤首先是将内核堆栈中得用户堆栈地址恢复到CPU堆栈指针寄存器中。

2、内核栈和用户栈区别
  内核栈是系统运行在内核态的时候使用的栈,用户栈是系统运行在用户态时候使用的栈。当进程由于中断进入内核态时,系统会把一些用户态的数据信息保存到内核栈中,当返回到用户态时,取出内核栈中的信息恢复出来,返回到程序原来执行的地方。用户栈就是进程在用户空间时创建的栈,比如一般的函数调用,将会用到用户栈。内核栈是属于操作系统空间的一块固定区域,可以用于保存中断现场、保存操作系统子程序间相互调用的参数、返回值等。用户栈是属于用户进程空间的一块区域,用户保存用户进程子程序间的相互调用的参数、返回值等。
  每个Windows 都有4g的进程空间,系统栈使用进程空间的低端部分,用户栈是高端部分。如果用户要直接访问系统栈部分,需要有特殊的方式。

为何要设置两个不同的栈?
共享原因:
  内核的代码和数据是为所有的进程共享的,如果不为每一个进程设置对应的内核栈,那么就不能实现不同的进程执行不同的代码。

安全原因:
如果只有一个栈,那么用户就可以修改栈内容来突破内核安全保护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值