Chinaunix首页 | 论坛 | 博客
  • 博客访问: 100403
  • 博文数量: 16
  • 博客积分: 1113
  • 博客等级: 少尉
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-31 13:36
文章分类

全部博文(16)

文章存档

2011年(4)

2010年(12)

分类: LINUX

2010-07-28 17:21:37

所有进程的祖先叫做进程0,idle 进程(swapper进程),它是在Linux 的初始化阶段从无到有创建的一个内核线程。这个祖先进程使用静态分配的数据结构(所有其他进程的数据结构都是动态分配的)

 

下面着重介绍一下进程0 内核栈的初始化过程!

head.S 中:

            lss stack_start,%esp

                ……

            ENTRY(stack_start)

                      .long init_thread_union+THREAD_SIZE

                      .long __BOOT_DS

表示加载内核栈,ss= __BOOT_DS,表示内核数据段,而 esp  指向从init_thread_union 开始的大小为THREAD_SIZE的内存处。

(init_thread_union C 代码中为初始化的全局变量,在汇编中被当作为label 也就是地址)

 

那么init_thread_union 是什么呢?

init_task.c:

               union thread_union init_thread_union

                          __attribute__((__section__(".data.init_task"))) =

                                      { INIT_THREAD_INFO(init_task) };

表示在内核的 .data.init_task 段定义一个共用体变量,并为其初始化。

按照THREAD_SIZE 对齐!!

 

thread_union 为:

               union thread_union {

                         struct thread_info thread_info;

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

};

THREAD_SIZE 定义为 4096

 

.data.init_task 段中开辟了4096 字节大小空间用于内核栈。低地址处存放thread_info 结构,剩下的作为内核栈。

 

让我们想象一下现在内存中栈的情况:

 

 

 

此时 esp 位于下一个4KB 内存单元的开始处,此时栈为空。(push 是先减减esp!)

 

因为进程0的数据结构由静态初始化,此时就可以获得当前进程(进程 0) current 进程描述符指针。

 

#define current get_current()

 

static inline struct task_struct * get_current(void)

{

         return current_thread_info()->task;

}

 

static inline struct thread_info *current_thread_info(void)

{

         struct thread_info *ti;

         __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));

         return ti;

}

 

因为此时内核栈并不为空,所以很容易就可以算出thread_info 结构的起始地址,因为在一页内存中,esp FFFFF000 相与 就可算出其基地址既thread_info 结构地址。thread_info结构的第一项就为其指向tss_struct 的指针,所以很容易就可得到current!!

阅读(2017) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~