转自:http://www.kerneltravel.net/kernel-book/%E7%AC%AC%E5%9B%9B%E7%AB%A0%20%E8%BF%9B%E7%A8%8B%E6%8F%8F%E8%BF%B0/4.4.1.htm

4.4.1进程内核栈

每个进程都有自己的内核栈。当进程从用户态进入内核态时,CPU就自动地设置该进程的内核栈,也就是说,CPU从任务状态段TSS中装入内核栈指针esp(参见下一章的进程切换一节)。

X86内核栈的分布如图4.2所示:

     
   
 
     

图4.2 内核栈的分布图

在Intel系统中,栈起始于末端,并朝这个内存区开始的方向增长。从用户态刚切换到内核态以后,进程的内核栈总是空的,因此,esp寄存器直接指向这个内存区的顶端。 在图4.2中,从用户态切换到内核态后,esp寄存器包含的地址为0x018fc00。进程描述符存放在从0x015fa00开始的地址。只要把数据写进栈中,esp的值就递减。

在/include/linux/sched.h中定义了如下一个联合结构:

union task_union {

struct task_struct task;

unsigned long stack[2408];

};

从这个结构可以看出,内核栈占8kb的内存区。实际上,进程的task_struct结构所占的内存是由内核动态分配的,更确切地说,内核根本不给task_struct分配内存,而仅仅给内核栈分配8K的内存,并把其中的一部分给task_struct使用。

task_struct结构大约占1K字节左右,其具体数字与内核版本有关,因为不同的版本其域稍有不同。因此,内核栈的大小不能超过7K,否则,内核栈会覆盖task_struct结构,从而导致内核崩溃。不过,7K大小对内核栈已足够。

把task_struct结构与内核栈放在一起具有以下好处:

·      内核可以方便而快速地找到这个结构,用伪代码描述如下:

task_struct = (struct task_struct *) STACK_POINTER & 0xffffe000

·      避免在创建进程时动态分配额外的内存

·      task_struct结构的起始地址总是开始于页大小(PAGE_SIZE)的边界。

最新文章

  1. 日期操作类--Date类
  2. asp.net如何将DataSet转换成josn并输出
  3. JQuery插件之图片轮播插件–slideBox
  4. 隐藏tabBar页面跳转后会再布局一次,
  5. php学习问题记录
  6. oracle中循环插入语句
  7. vb安装过程中 ntvdm.exe[9696]中发生未处理的win32异常
  8. Cortex-M3知识点
  9. Linux内核驱动将多个C文件编译成一个ko文件的方法——每一个C文件中都有module_init与module_exit
  10. POJ - 3249 Test for Job (DAG+topsort)
  11. scrapy初试水 day01
  12. 【BZOJ4869】相逢是问候(线段树,欧拉定理)
  13. python--元祖和字典
  14. ProgressDialog替代
  15. java中最常见的几种运行时异常,你get了吗?
  16. react+typescript报错集锦<持续更新>
  17. Navicat Premium连接各种数据库
  18. POJ 3080 Blue Jeans 后缀数组, 高度数组 难度:1
  19. 原生js的博客
  20. ubuntu系统

热门文章

  1. 30天,App创业从0到1【7.12西安站】
  2. Java hashCode
  3. hadoop 文件系统API操作
  4. nginx 日志分析
  5. Excessive AWR Growth From Partitioned Objects Such as SYS.WRH$_EVENT_HISTOGRAM Causing Sysaux to Grow
  6. 关键字 self
  7. Java基础之处理事件——应用程序中的语义事件监听器(Sketcher 5 with element color listeners)
  8. 将 IDENTITY 转换为数据类型 int 时出现算术溢出错误。
  9. data type Migration from MySQL to PostgreSQL
  10. PostgreSQL中关于关键字(保留字)在表名和字段名中的应用文件解决