zoukankan      html  css  js  c++  java
  • 可执行程序工作原理

    2018-2019-120189224 《庖丁解牛Iinux内核分析》第八周学习总结

    ELF

    程序编译

    链接与库

    程序装载实验

    实验要求:
    理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节;​
    编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接,编程练习动态链接库的这两种使用方式,详细内容参考本周第二节;
    使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve ,验证您对Linux系统加载可执行程序所需处理过程的理解,详细内容参考本周第三节;推荐在实验楼Linux虚拟机环境下完成实验。
    实验过程如下:
    1.更新menu后用test.c覆盖test_exec.c

    int Exec(int argc, char argv[])
    
    {
    
    int pid;
    
    / fork another process /
    
    pid = fork();
    
    if (pid < 0)
    
    {
    
    / error occurred /
    
    fprintf(stderr,"Fork Failed!");
    
    exit(-1);
    
    }
    
    else if (pid == 0)
    
    {
    
    / child process /
    
    printf("This is Child Process!
    ");
    
    execlp("/hello","hello",NULL);
    
    }
    
    else
    
    {
    / parent process /
    
    printf("This is Parent Process!
    ");
    
    / parent will wait for the child to complete*/
    
    wait(NULL);
    
    printf("Child Complete!
    ");
    
    }
    
    }
    

    2.编译的时候执行了hello.c,并把init 和 hello 放到了rootfs.img目录下,所以在执行exec命令的时候就相当于自动了加载了hello这个程序。如下所示:

    3.gdb跟踪分析
    execve 是比较特殊的系统调用,exec_binprm 在保存了 bprm 后调用该函数来进一步操作,execve 加载的可执行文件会把当前的进程覆盖掉,返回之后就不是原来的程序而是新的可执行程序起点。这个函数除了保存 pid 以外,还执行了 search_binary_handler 来查询能够处理相应可执行文件格式的处理器,并调用相应的load_binary 方法以启动新进程。

    load_elf_binary 调用 start_thread 函数。修改 int 0x80 压入内核堆栈的 EIP,当 load_elf_binary 执行完毕,返回至 do_execve 再返回至 sys_execve 时,系统调用的返回地址,即 EIP 寄存器,已经被改写成了被装载的 ELF 程序的入口地址。



    hello的入口地址和new_ip的值都是0x8048d0a,对hello程序链接到了执行程序中
    Linux 系统通过用户态 execve 函数调用内核态 sys_execve 系统调用,负责将新的程序代码和数据替换到新的进程中,打开可执行文件,载入依赖的库文件,申请新的内存空间,最后执行 start_thread 函数设置 new_ip 和 new_sp,完成新进程的代码和数据替换,然后返回并执行新的进程代码。

    总结

    可执行文件描述了如何初始化一个新的执行上下文。在init的时候会将支持的可执行程序解析程序注册添加到内核的链表中,在对可执行文件进行解析时,从链表头开始找,找到匹配的处理函数就对其进行解析。在shell中启动一个可执行程序时,会创建一个新进程,通过覆盖父进程的进程环境,将用户态堆栈清空,获得需要的执行上下文环境。命令行参数和环境变量会通过shell传递给execve,excve通过系统调用参数传递,传递给sys_execve,最后sys_execve在初始化新进程堆栈的时候拷贝进去。当execve()系统调用终止且进程重新恢复它在用户态执行时,执行上下文被大幅度改变,要执行的新程序已被映射到进程空间,从elf头中的程序入口点开始执行新程序。如果这个新程序是静态链接的,那么这个程序就可以独立运行,elf头中的这个入口地址就是本程序的入口地址;如果这个新程序是动态链接的,那么还需要装载共享库,elf头中的这个入口地址是动态链接器ld的入口地址。load_elf_binary->start_thread(…)通过修改内核堆栈中EIP的值作为新程序的起点。

  • 相关阅读:
    C语言实现—学生成绩管理系统
    C++ 制作一个“测运”小游戏-rand()函数的应用
    C语言实现-航空订票系统(飞机订票系统)
    测试随笔功能
    ASP.Net 连接多个数据库之间的切换
    190906mysql常用语法
    190327 Python登录接口
    190221 百元百鸡
    181102 Windows下安装kivy(用python写APP)
    181102 Python环境搭建(安装Sublime Text3)
  • 原文地址:https://www.cnblogs.com/20189224sxy/p/10054952.html
Copyright © 2011-2022 走看看