Linux内核如何装载和启动一个可执行程序

一、ELF可执行文件格式

  • ELF格式分类:
  可重定位文件:用来和其他object文件一起创建可执行文件和共享文件

  可执行文件:指出应该从哪里开始执行

  共享文件:主要是.so文件,用来被链接编辑器和动态链接器链接
  (1)对ELF头的描述告诉系统如何创建一个进程的内存映像,section头表包含了描述文件sections的信息。当创建或增加一个进程映像时,理论上它会把

程序段拷贝到虚拟内存中某个段

  (2)ELF文件的头部规定了许多与二进制兼容性相关的信息。所以在加载ELF文件的时候,必须先加载头部,分析ELF的具体信息

  (3)entry代表刚加载过新的可执行文件之后的程序的入口地址,头部后是代码和数据,进程的地址空间是4G,上面的1G是内核用,下面的3G是程序使用。

默认的ELF头加载地址是0x8048000
  • 静态链接的ELF可执行文件和进程的地址空间:

1.可执行文件加载到内存

   加载效果:将代码段数据加载到内存中,再把数据加载到内存,默认从0x8048000地址开始加载

   启动一个刚加载过可执行文件的进程时,可执行文件加载到内存之后执行的第一条代码地址

   一般静态链接会将所有代码放在一个代码段,而动态链接的进程会有多个代码段

2.流程

  (1) 分析头部

  (2) 查看是否需要动态链接。如果是静态链接的ELF文件,那么直接加载文件即可。如果是动态链接的可执行文件,那么需要加载的是动态链接器

  (3) 装载文件,为其准备进程映像

  (4) 为新的代码段设定寄存器以及堆栈信息

二、实验内容

更新menu后用test.c覆盖test_exec.c,然后打开test.c(shitf+G 直接到文件尾的快捷键)

可以看到添加了exec命令,执行一个程序的功能。

其函数内容为

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 */
execlp("/bin/ls","ls",NULL);
}
else
{
/* parent process */
/* parent will wait for the child to complete*/
wait(NULL);
printf("Child Complete!");
exit(0);
}
}

由于在Makefile中做了修改。编译的时候执行了hello.c

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

下面是通过gdb进行跟踪分析

设置b sys_execve ,b load_elf_binary 断点

可以先停在sys_execve然后设置其他断点

new_ip是返回到用户态的第一条指令的地址

此时可以通过po new_ip和新窗口的 readelf -h helloc查看入口地址是否一致



可以看到hello的入口地址和new_ip的值都是0x8048d0a 。说明对hello程序链接到了执行程序中。

三、总结

在创建一个新的用户态堆栈的时候,实际上是把命令行参数的内容和环境变量的内容通过指针的方式传递到系统调用的内核处理函数的,内核处理函数在创建一个新的可执行堆栈的时候会将

命令行参数的内容和环境变量的内容拷贝到用户态堆栈里面来初始化新的可执行程序执行的上下文环境,先函数调用参数传递,在系统调用参数传递

shell程序 -> execve -> sys_execve
  • sys_execve的内部处理过程 ( 装载和启动一个可执行程序依次调用以下函数):
sys_execve() -> do_execve() -> do_execve_common() -> exec_binprm() -> search_binary_handler() -> load_elf_binary() -> start_thread()

Linux内核原理第八次作业的更多相关文章

  1. 2018-2019-1 20189221 《Linux内核原理与分析》第八周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第八周作业 实验七 编译链接过程 gcc –e –o hello.cpp hello.c / gcc -x cpp-o ...

  2. 2017-2018-1 20179205《Linux内核原理与设计》第八周作业

    <Linux内核原理与设计>第八周作业 视频学习及操作分析 预处理.编译.链接和目标文件的格式 可执行程序是怎么来的? 以C语言为例,经过编译器预处理.编译成汇编代码.汇编器编译成目标代码 ...

  3. 2019-2020-1 20199329《Linux内核原理与分析》第八周作业

    <Linux内核原理与分析>第八周作业 一.本周内容概述: 理解编译链接的过程和ELF可执行文件格式 编程练习动态链接库的两种使用方式 使用gdb跟踪分析一个execve系统调用内核处理函 ...

  4. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  5. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  6. 20169207《Linux内核原理及分析》第十三周作业

    第一周作业::对Linux的基本知识进行了了解,并对基本操作进行熟悉和应用. 第二周作业::了解了冯诺依曼体系结构.各种寄存器的功能和汇编指令的作用和功能. 第三周作业::这周主要了解了Linux系统 ...

  7. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  8. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  9. 2018-2019-1 20189221 《Linux内核原理与分析》第七周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第七周作业 实验六 分析Linux内核创建一个新进程的过程 代码分析 task_struct: struct task ...

随机推荐

  1. springCloud全家桶

    Spring Cloud 入门教程(一): 服务注册 eureka是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳,在默认情况下erureka server也是一个eure ...

  2. Angular 学习笔记 (组件沟通的思考)

    组件指令间经常需要沟通 我们知道的方式有 input output service inject viewchild contentchild templateRef template variabl ...

  3. Django+七牛上传+查看+下载文件相关函数,新整理未完全测试

    M class File(models.Model): # 文档模型 name = models.CharField(max_length=255) staff = models.ForeignKey ...

  4. java poi excel操作 下拉菜单 及数据有效性

    1 private InputStream updateTemplateStyleHSSF(InputStream inputStream,CsCustCon csCustCon) throws IO ...

  5. laravel进行单元测试的时候如何模拟数据库以及mockery的调用

    单元测试是独立的,所谓的独立是指有独立的运行容器,独立的数据库. 这样做有什么好处呢? (1). 不会跟正常的容器产生冲突,继而影响正常业务. (2). 数据库独立防止数据被修改影响单元测试结果. 这 ...

  6. EOS使用

    公司要玩区块链,听说EOS交易快,就弄来玩玩.弄了一天终于编译成功了. Scanning dependencies of target nodeos [%] Building CXX object p ...

  7. QChart绘制折线区域

    效果图: 代码: // 创建折线上点的序列 QLineSeries *splineSeries = new QLineSeries(); //QSplineSeries *splineSeries = ...

  8. Oracle判断周末

    有些业务场景下会有择出周末的需求,具体判断语句如下: 1.SELECT TO_CHAR(TO_DATE(DATA_DATE,'YYYY-MM-DD),'D') FROM DUAL; 如果DATA_DA ...

  9. vue组件利用formdata图片预览以及上传

    转载修改 在项目中直接新建一个单文件页,复制一下代码即可       upload组件: <template> <div class="vue-uploader" ...

  10. 高性能消息中间件——NATS

    前 言 这段时间我的主要工作内容是将公司系统中使用的RabbitMQ替换成NATS,而此之前我对Nats一无所知.经过一段时间紧张的学习和开发之后我顺利的完成了任务,并对消息中间件有了更深的了解.在此 ...