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

再次看到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, &current->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页的图

080723092358.jpg

这个图的理解是从系统空间堆栈中减掉一个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的计算,看一下这个图

080723095420.jpg

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值