Kernel分析—进程创建后用户栈是怎么分配的

1.  Shell终端中执行可执行文件过程简述:

(1)读取用户由键盘输入的命令行。

(2)分析命令,以命令名作为文件名,并将其它参数改造为系统调用execve()内部处理所要求的形式。

(3)终端进程调用fork()建立一个子进程。

(4)终端进程本身用系统调用wait4()来等待子进程完成(如果是后台命令,则不等待)。当子进程运行时调用execve(),子进程根据文件名(即命令名)到目录中查找有关文件(这是命令解释程序构成的文件),将它调入内存,执行这个程序(解释这条命令)。

(5)如果命令末尾有&号(后台命令符号),则终端进程不用系统调用wait4()等待,立即发提示符,让用户输入下一个命令,转(1)。如果命令末尾没有&号,则终端进程要一直等待,当子进程(即运行命令的进程)完成处理后终止,向父进程(终端进程)报告,此时终端进程醒来,在做必要的判别等工作后,终端进程发提示符,让用户输入新的命令,重复上述处理过程。

 

 

 

2. 进程地址空间中用户栈的分配

进程地址空间由mm_struct结构描述,每个进程只存在一个地址空间。该结构伴随着进程的创建而创建。其中用start_stack来表示用户栈的起始地址。

(1) 进程创建,并建立进程地址空间。

do_fork

|- > copy_process

         |- > dup_task_struct

         |- > copy_mm

 

(2) 通过系统调用execve执行可执行程序,并重新分配用户栈。

    基本处理流程:

    do_execve_common - > exec_binprm - > search_binary_handler - > load_binary===load_elf_binary

    在load_elf_binary 函数中,完成用户栈 start_stack 的初始化, bpr->p 在setup_arg_pages中赋值 。

其中:

♦  personality 中默认是没有设置ADDR_NO_RANDOMIZE。

    randomize_va_space是由/proc/sys/kernel/randomize_va_space决定,

     通过查看目前设置为 2.

♦ randomize_stack_top函数:

 

♦ setup_arg_pages函数:

int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack)
{
.....

#ifdef CONFIG_STACK_GROWSUP   // 没有配置

....

#else

      stack_top = arch_align_stack(stack_top);
      stack_top = PAGE_ALIGN(stack_top);

if (unlikely(stack_top < mmap_min_addr) ||
unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
return -ENOMEM;

stack_shift = vma->vm_end - stack_top;

bprm->p -= stack_shift;
mm->arg_start = bprm->p;

#endif

.....

}

3. 实验验证

 

       

 

 



posted @ 2022-11-29 20:52  天地—蜉蝣  阅读(121)  评论(0)    收藏  举报