linux下的内存分为用户态内存和内核态内存,一般4个G内存,3个G的分给用户态,1个G分给内核态。
linux进程有时需要调用内核资源时,如读写文件,io读写等,这时候是通过系统调用实现对内核资源的访问的,在访问内核资源前是用户栈,经过系统调用进入到内核态时,cpu的状态也由用户态变为内核态,访问的内存就是内核态下管理的内存了-内核栈,对内核里的资源访问完返回,内存又回到了用户栈,cpu也回到用户态。
在Linux 0.12系统中,所有中断服务程序都属于内核代码。如果一个中断产生时任务正在用户代码中执行,那么该中断就会引起CPU特权级从3级到0级的变化,此时CPU就会进行用户态堆栈到内核态堆栈的切换 *** 作。CPU会从当前任务的任务状态段TSS中取得新堆栈的段选择符和偏移值。因为中断服务程序在内核中,属于0级特权级代码,所以48位的内核态堆栈指针会从TSS的ss0和esp0字段中获得。在定位了新堆栈(内核态堆栈)之后,CPU就会首先把原用户态堆栈指针ss和esp压入内核态堆栈,随后把标志寄存器eflags的内容和返回位置cs、eip压入内核态堆栈。内核的系统调用是一个软件中断,因此任务调用系统调用时就会进入内核并执行内核中的中断服务代码。此时内核代码就会使用该任务的内核态堆栈进行 *** 作。同样,当进入内核程序时,由于特权级别发生了改变(从用户态转到内核态),用户态堆栈的堆栈段和堆栈指针以及eflags会被保存在任务的内核态堆栈中。而在执行iret退出内核程序返回到用户程序时,将恢复用户态的堆栈和eflags。
如果一个任务正在内核态中运行,那么若CPU响应中断就不再需要进行堆栈切换 *** 作,因为此时该任务运行的内核代码已经在使用内核态堆栈,并且不涉及优先级别的变化,所以CPU仅把eflags和中断返回指针cs、eip压入当前内核态堆栈,然后执行中断服务过程。
当然是,进程生成时,会被分配一个task_struct 结构(常说的进程控制块),2.4内核中,在task_struct 结构体上面的7KB空间就是。加上task_struct结构本身(1KB),进程内核栈共8KB(两个页面 ),不会动态扩展,所以非常有限(你会见到内核代码用"大块"内存都会kmalloc申请的,就是这个原因)。2.6内核的没注意,不知一样否。详见:《Linux内核源代码情景分析(上)》267页。为什么会在内核的原因是CPU的保护机制,中断处理需要更高的权限(可能执行硬件相关的 *** 作),故要在0级,不会在用户区的。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)