您的位置:首页 > 运维架构 > Linux

linux中关于创建子进程系统堆栈的分析

2013-03-21 18:56 417 查看
linux中关于创建子进程系统堆栈的分析

linux中关于创建子进程系统堆栈的分析
来源: ChinaUnix博客  日期: 2008.07.23 09:57 (共有条评论)

我要评论
再次看到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个字节.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: