zoukankan      html  css  js  c++  java
  • 进程装载过程分析(execve系统调用分析)

    最近一段时间在学习linux内核,这里将进程启动的过程的一些心得体会记录一下。

    1、进程启动

      linux环境下我们启动一个程序一般都是通过shell拉起来的。或者通过一个程序调用exec系列函数进行进程替换的。

      其实这两种方式实质是一样的,shell拉起也是调用的exec系列函数;所以我们就以第二种方式用代码来分析整个装载过程。

    2、程序代码

      首先我们来看下我们的实例程序代码。

       为了好跟踪内核代码,所以这里通过qemu模拟了linux和文件系统。上左图为主进程,主进程fork了一个子进程,子进程最后调用exec*将自己替换为hello进程(),

      hello进程代码为右图。

    3、 内核代码走读

      其实这里主要就是跟踪exec* 系统调用在内核中的执行,exec*系列函数都是execve的封装例程,execve系统调用最终对应的系统调用处理函数为sys_execve。

      

      sys_execve——> do_execve——>do_execve_common调用过程,do_execve_common 里面的实际上就是在组装 struct linux_binprm结构体。

      其主要调用exec_binprm

     

    最终找到elf的加载函数,开始正式按照elf格式进行加载。

    ,通过上图,可以看到“current_pt_regs”这个就是将当期进程的寄存器堆取出来(eax、ebx……)。

    然后“elf_entry”这个就是新的进程的入口,也就是这里是在准备新进程的堆栈信息、执行环境,实际上start_thread就是将原来的进程的堆栈信息全给替换为了新的进程的堆栈.

    4、调试跟踪

     

    如上图可以看到在start_thread函数中将新的进程的入口函数加载到堆栈中了,而进程入口就是进行elf文件中的entry point address.于是当进程返回用户空间时,就从新的进程入口开始执行了,于是进程就被替换成新的进程了——偷梁换柱

    5、总结

      其实我们上面只分析了进程为静态链接的情况。如果是动态链接,老进程的堆栈入口将不是elf文件的开始。二手ld动态加载器,如下图代码所示:

    我们进程的加载都是通过exec系统调用在内核中通过堆栈的替换 来偷梁换柱完成的。可以比喻为当一个人走进一个房间后(内核),等他出来时他的灵魂已经被换成另一个人了。

  • 相关阅读:
    QT删除QWidget或QLayout下的控件
    OSG HUD实现类似ArcGIS制图中图例效果(色块+标注)
    QT简易画板练习
    展望
    打字比赛日前
    学习的第一天
    SpringBoot之CommandLineRunner启动执行任务
    java根据ip获取城市
    springboot项目中, 同一浏览器JSESSIONID互相覆盖问题
    eclipse的spring项目中,alt+/无提示或按多次才正确提示
  • 原文地址:https://www.cnblogs.com/tjyuanxi/p/9313253.html
Copyright © 2011-2022 走看看