linux可执行文件的加载和运行之一(2)

linux可执行文件的加载和运行之一

  用户栈位于进程空间的最高部份.那进程初始化时,用户栈存放的是什么呢?是参数.进程在执行时会到栈中去取运行时所需的参数.这里所谓的参数包含了可执行程序所带的参数和环境变量.例如:在shell上执行”echo hello,eric” .echo程序带有二个参数.argv[0] = “echo”,argv[1] = “hello,eric”即第一个参数为程序名称.其后的参数分别是运行进程所带的参数.当然,在上面这个例子中没有列出环境变量.一般的.在参数后面都跟了一个NULL.表示参数已经结束了,在上例中argv[1]后面的一个字节是NULL.如下图所示:

linux可执行文件的加载和运行之一 这样程序在运行的时候就可以方便的确定参数及环境变量的个数. 现在,我们可以分析代码了.bprm_mm_init()是bprm的初始化函数,我们跟踪进去看它是怎么样初始化的.int bprm_mm_init(struct linux_binprm *bprm)
{
  int err;
  struct mm_struct *mm = NULL;
  //分配一个mm
//mm_alloc我们在进程创建的时候已经分析过了,值得注意的是,它会调用mm_init()来为
//进程的用户空间建立PGD->PMD映射
  bprm->mm = mm = mm_alloc();
  err = -ENOMEM;
  if (!mm)
    goto err;
  err = init_new_context(current, mm);
  if (err)
    goto err;
  //初始化bprm->mm
  err = __bprm_mm_init(bprm);
  if (err)
    goto err;
  return 0;
err:
  if (mm) {
    bprm->mm = NULL;
    mmdrop(mm);
  }
  return err;
}
重点是在__bprm_mm_init():static int __bprm_mm_init(struct linux_binprm *bprm)
{
  int err = -ENOMEM;
  struct vm_area_struct *vma = NULL;
  struct mm_struct *mm = bprm->mm;
  //分配一个VMA
  bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
  if (!vma)
    goto err;
  down_write(&mm->mmap_sem);
  vma->vm_mm = mm;
  //STACK_TOP_MAX:进程用户空间的最高值
  //对应进程的栈顶
  vma->vm_end = STACK_TOP_MAX;
  vma->vm_start = vma->vm_end - PAGE_SIZE;
  vma->vm_flags = VM_STACK_FLAGS;
  vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
  //将VM插入mm表示的进程空间结构
  err = insert_vm_struct(mm, vma);
  if (err) {
    up_write(&mm->mmap_sem);
    goto err;
  }
  mm->stack_vm = mm->total_vm = 1;
  up_write(&mm->mmap_sem);
  //bprm->p:用户栈的栈指针
  bprm->p = vma->vm_end - sizeof(void *);
  return 0;
err:
  if (vma) {
    bprm->vma = NULL;
    kmem_cache_free(vm_area_cachep, vma);
  }
  return err;
}
上面的操作看起来比较隐晦,我们把它的操作用下面的图表示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值