Chinaunix首页 | 论坛 | 博客
  • 博客访问: 579680
  • 博文数量: 353
  • 博客积分: 1104
  • 博客等级: 少尉
  • 技术积分: 1457
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-23 23:02
个人简介

1、刚工作时做Linux 流控;后来做安全操作系统;再后来做操作系统加固;现在做TCP 加速。唉!没离开过类Unix!!!但是水平有限。。

文章存档

2015年(80)

2013年(4)

2012年(90)

2011年(177)

2010年(1)

2009年(1)

分类:

2011-12-21 21:30:46

再次看到LINUX中的fork系统调用时,读到copy_thread(),2.4内核代码是这样的
 
int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 unsigned long unused,
 struct task_struct * p, struct pt_regs * regs)
{
 struct pt_regs * childregs;
 childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
 struct_cpy(childregs, regs);
 childregs->eax = 0;
 childregs->esp = esp;
 p->thread.esp = (unsigned long) childregs;
 p->thread.esp0 = (unsigned long) (childregs+1);
 p->thread.eip = (unsigned long) ret_from_fork;
 savesegment(fs,p->thread.fs);
 savesegment(gs,p->thread.gs);
 unlazy_fpu(current);
 struct_cpy(&p->thread.i387, ¤t->thread.i387);
 return 0;
}
这个函数就是复制父进程堆栈的内容到子进程的堆栈中去,并且设置一下子进程的task_struct内容,我们重点关心蓝色部分,也就是子进程系统堆栈的分析部分
特别是这句代码
((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
P是新建的进程的task_struct结构,他是在新分配的二个页面(THREAD_SIZE)的最低下,而pt_regs是系统的保存系统调用时或者中断时寄存器的数据结构,如果P+THREAD_SIZE就代表子进程的堆栈的最顶端也就是ESP,如果转换成pt_regs结构再减去1,这里的计算结果实在是太模糊,,如果按照pt_regs结构减掉1的话就是分配了一个pt_regs,那也就是说Linux内核情景分析书中302页的图
这个图的理解是从系统空间堆栈中减掉一个pt_regs结构,实际上变相分配堆栈给pt_regs了。这样的计算方法很多,但是我们再看一下2.6.24内核是如何清晰的描绘的
首先2.6.24内核在task_struct结构中增加了一个void类型的指针stack,使它指向进程的系统空间堆栈顶端这是在do_fork()-->copy_process()-->dup_task_struct()函数中实现的:
struct thread_info *ti;
 ti = alloc_thread_info(tsk);
 if (!ti) {
  free_task_struct(tsk);
  return NULL;
 }
 *tsk = *orig;
 tsk->stack = ti;
这里通过下面函数
#define alloc_thread_info(tsk) ((struct thread_info *) \
 __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)))
这里很明显其实就是分配系统的堆栈,并把地址转换成thread_info结构指针
这样就得到了系统的堆栈指针,然后同样通过copy_thread()-->task_pt_regs()
#define task_pt_regs(task)                                             \
({                                                                     \
       struct pt_regs *__regs__;                                       \
       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
       __regs__ - 1;                                                   \
})
#define task_stack_page(task) ((task)->stack)
#define KSTK_TOP(info)                                                 \
({                                                                     \
       unsigned long *__ptr = (unsigned long *)(info);                 \
       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
})
 
好了我们再次看到上面的代码蓝色部分取出了刚才的系统堆栈指针,然后我们看到他有一个减8的计算,看一下这个图

为什么要减8呢,我们分析一下原来系统调用时或者中断时的情况,如果优先级别一样就不会把SS,ESP压入内核栈,这时候pt_regs结构体中的esp,xss不存在,为了防止非法访问,总在内核栈上空8个字节.

阅读(631) | 评论(0) | 转发(0) |
0

上一篇:Git Cheat Sheet

下一篇:IP套接口选项(转)

给主人留下些什么吧!~~