进程空间与系统空间(一)

  上回说今回要讲的是do_page_fault,所以呢我们今回就不讲do_page_fault了。是的,不讲这个了。这有点不按常理出牌,但是我这样做有我的理由,你们不要有任何的猜忌,just believe me!

  有些话要说在前头,我写这些文章的目的不是为了和大家交流学习心得更不是想传授什么知识给读者,我写这些东西完全是为了聊以自慰,打发一下无聊的时光,在这个网速常常只有几K的环境下,应了那句老话:寂寞难耐。

  在现代操作系统中有一个很重要很重要的概念,就是进程空间和系统空间,貌似这是两个概念。。。。。。如果你能在脑海里面很清楚的把进程空间和系统空间给描绘出来,那么你在linux内核上就已经小有成就了(这话是我说的,爱信不信)。所以接下来我想说一说这两个概念。

  要了解这两个空间我们还需要很多铺垫知识。。所以我们不要着急,牛奶会有的,面包会有的,一切都会好起来的。

  我们第一个要说的概念是系统空间堆栈。如果非要咬文嚼字的话,我们要说的应该是系统空间栈,因为事实上,堆和栈是两个概念的东西。

  栈这个东西,老爷看官们都懂吧?我们可以把栈理解为程序代码运行时用来存放一些临时变量的容器。调用函数的时候也是需要用到栈来传递参数的,所有在函数内部定义的变量也是在代码运行时才存放在栈中的,所以在函数内部的变量才会被称为局部变量。好了,普及知识就说到这了。

  当进程通过中断调用或者系统调用进入到内核空间的时候,她要抛弃掉原来的用户空间栈,转而去使用系统空间栈。为什么用户进程要抛糠妻呢?这其实与cpu架构相关。

  在x86架构中有4个特权级0到3,数字0表示最高特权级,3表示最低特权级。linux 内核只用到0和3这两个特权级,0给系统空间,3给用户进程空间。intel架构规定不同特权级之间的代码进行切换的时候,栈是需要更换的。这是一个很重要的知识点,大家必须谨记.

  我看了一下3.10.5的内核,该内核规定的系统空间栈也是8K,和2.4内核是差不多的,大家可以去参考一下《Linux内核情景分析》这本书。

  我们来看一下新版本的内核(如果不特别注明,以后所贴的代码都是3.10.5内核里面的代码)是怎么定义这个系统空间栈的

#define INIT_TSS  {        

  .x86_tss = {        

  .sp0  = sizeof(init_stack) + (long)&init_stack,

  .ss0  = __KERNEL_DS,     

  .ss1  = __KERNEL_CS,     

  .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,   

  },         

  .io_bitmap  = { [0 ... IO_BITMAP_LONGS] = ~0 },  

  }

  这是个宏,其他字段是什么意思我不想说,我们只关注这一句:.sp0 = sizeof(init_stack) + (long)&init_stack

  这句话的意思是把系统栈的栈顶赋值给栈寄存器esp.我们仔细分析一下这一句,首先init_stack也是一个宏定义。

#define init_stack (init_thread_union.stack)

  init_thread_union是一个共用体,定义如下:

  union thread_union init_thread_union __init_task_data =

  { INIT_THREAD_INFO(init_task) };

  由此可以看出init_thread_union是一个thread_union类型的共用体。我们再去看一下这个thread_union(我知道你看的很烦。。我写着更烦,互相体谅一下吧。)

//includelinuxSched.h

union thread_union {

  struct thread_info thread_info;

  unsigned long stack[THREAD_SIZE/sizeof(long)];

  };

  看到了吧。。最上面的那个init_stack最后会被重定义为这里的stack数组.

  unsigned long stack[THREAD_SIZE/sizeof(long)]

  我们算一下这个stack数组静态定义的空间有多大就知道内核给每个进程分配的系统空间栈有多大了。THREAD_SIZE定义如下:

#define THREAD_SIZE  (PAGE_SIZE << THREAD_SIZE_ORDER)

#define THREAD_SIZE_ORDER 1

  PAGE_SIZE表示物理页的大小,是4K,左移1位,即是4K*2=8K。所以THREAD_SIZE数值为8K,这是一个long型的数组,给这个数组分配的空间为8k/sizeof(long)*sizeof(long),单位为字节。最后算出来也是8K,如果你一时算不出来,那么建议先去撸几局LOL,让脑袋清醒一下。   结案陈词:内核给系统空间分配的栈为8K。这个栈是静态的栈。大小已经定了,所以大家在写驱动程序或者中断服务程序的时候不要定义太大的局部变量。

原文地址:https://www.cnblogs.com/Blue-Moon/p/3332301.html