1.问题描述

在前面的文章中,学习了在Linux系统之中如何创建一个新进程进行追踪,本文将围绕编译链接的过程和ELF可执行文件格式,对Linux内核装载和启动一个可执行程序。

2.解决过程

2.1 ELF文件

(1)可重定位文件:保存代码和适当数据,用来和其他object文件一起创建可执行文件或者共享文件,即.o文件。

(2)可执行文件:保存用来执行的程序,该文件指出了exec(BA_OS)如何来创建程序进程映像。

(3)共享目标文件:共享库,是指可以被可执行文件或其他库文件使用的目标文件,如标准C的库文件libc.so,只有一堆函数可供其他可执行文件调用。

2.2 ELF文件程序编译

程序经过的四个步骤:

预处理:编译器将C程序的头文件编译进来,还有宏的替换,可以用gcc的参数-E来参看。

gcc -E louhao.c -o louhao.i

编译:这个阶段编译器主要做词法分析、语法分析、语义分析等,在检查无错误后后,把代码翻译成汇编语言。可用gcc的参数-S来参看。

gcc -S louhao.i -o louhao.s

汇编:汇编器as将louhao.s 翻译成机器语言保存在louhao.o 中(二进制文本形式)。

gcc -c louhao.s -o louhao.o

链接:链接器负责处理多个.o文件的并入,结果得到louhao文件,它就是一个可执行的目标文件。

gcc louhao.o -o louhao

2.3 静态链接和动态链接

静态链接:在编译时直接将需要的执行代码复制到最终可执行的文件中,优点是代码的装载速度快,执行速度也比较快,对外部环境依赖度低。编译时会把所有需要的代码都链接进去,应用程序相对比较大。缺点是如果多个应用程序使用同一库函数,会被装载多次,浪费内存。

动态链接:在编译时不直接复制可执行代码,而是通过一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统。操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库去执行代码,最终达到运行时链接的目的。优点是多个程序可以共享同一段代码,而不需要在磁盘上存储多个复制。缺点时在运行时加载,可能会影响程序的前期执行性能,而且对库的依赖度极高。

2.4 装载和启动一个可执行程序

将menu目录删除,利用git命令克隆一个新的menu目录,然后用test_exec.c覆盖test.c:



重新编译rootfs:



可以看到test.c中增加了exec函数,执行exec指令,显示如下:



返回LinuxKernel目录,shift+ctrl+o水平分割,用gdb设置断点:



c执行至start_thread断点暂停:



输入exec:



继续执行:



关闭qume,在menu目录下查看hello可执行文件:



给出对exec函数的分析:

int do_execve(struct filename *filename,
const char __user *const __user *__argv,
const char __user *const __user *__envp)
{
return do_execve_common(filename, argv, envp);
} static int do_execve_common(struct filename *filename,
struct user_arg_ptr argv,
struct user_arg_ptr envp)
{
// 检查进程的数量限制 // 选择最小负载的CPU,以执行新程序
sched_exec(); // 填充 linux_binprm结构体
retval = prepare_binprm(bprm); // 拷贝文件名、命令行参数、环境变量
retval = copy_strings_kernel(1, &bprm->filename, bprm);
retval = copy_strings(bprm->envc, envp, bprm);
retval = copy_strings(bprm->argc, argv, bprm); // 调用里面的 search_binary_handler
retval = exec_binprm(bprm); // exec执行成功 } static int exec_binprm(struct linux_binprm *bprm)
{
// 扫描formats链表,根据不同的文本格式,选择不同的load函数
ret = search_binary_handler(bprm);
// ...
return ret;
}

3.总结

本文主要学习了编译链接的过程和ELF可执行文件格式,对Linux内核装载和启动一个可执行程序。可执行文件开始执行的起点在修改调用execve系统调用时压入内核堆栈的EIP寄存器的值,此时标志着当前进程的可执行文件已经被完全替换为新的可执行文件,但实际上开始执行可执行文件中的指令还需要等到执行可执行文件中定义的入口地址的位置。如果是静态链接的可执行文件,那么eip指向该elf文件的文件头e_entry所指的入口地址;如果是动态链接,eip指向动态链接器。

2019-2020-1 20199310《Linux内核原理与分析》第八周作业的更多相关文章

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

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

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

    <Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...

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

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

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

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

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

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

  6. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  7. 2019-2020-1 20209313《Linux内核原理与分析》第二周作业

    2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...

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

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

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

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

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

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

随机推荐

  1. list容器排除重复单词的程序

    #include<iostream> #include<fstream> #include<string> #include<algorithm> #i ...

  2. G 树的难题

    时间限制 : 10000 MS   空间限制 : 165536 KB 评测说明 : 1s,128m 问题描述 给出一个无根树.树有N个点,边有权值.每个点都有颜色,是黑色.白色.灰色这三种颜色之一,称 ...

  3. Lisp-01: 相关开发环境配置部署

    Common Lisp 学习笔记系列01 要学一门编程语言,首先需要将语言的环境配置好.如果想要个直接上手的环境,感谢日本的大神 Shirakumo,打造了一个 Common Lisp 的 IDE - ...

  4. 自动由@3x图片生成@2x和@1x的图片 - Xcode插件

    原文:http://www.cocoachina.com/bbs/read.php?tid=277187 生成@3x图片对应的@2x和@1x版本--RTImageAssets 关键字:Xcode插件, ...

  5. CSS制作小旗子与小箭头

    CSS制作小旗子与小箭头 效果图如下: 小旗子效果图 小箭头效果图 小旗子效果 以下是具体实现代码: <div class="container"> <div c ...

  6. Redis操作,数据库操作

    Redis操作,数据库操作 案例1:源码安装Redis缓存服务 案例2:常用Redis数据库操作指令 案例3:配置Redis主从服务器 1 案例1:源码安装Redis缓存服务 1.1 问题 本案例要求 ...

  7. 检查mysql表碎片化脚本

    #!/bin/sh echo -n "MySQL username: " ; read username echo -n "MySQL password: " ...

  8. 【JavaScript】js01

    一,javascript 历史. netscape -> 浏览器. -> livescript 微软 -> jscript netscape -> ecma 组织 -> ...

  9. spark 独立应用编程之 Java 编程

    文章更新于:2020-04-03 按照惯例,文件附上链接放在文首. 文件名:apache-maven-3.6.3-bin.tar.gz 文件大小:9.1 MB 下载链接:https://www.lan ...

  10. JUC——检视阅读

    JUC--检视阅读 参考资料 JUC知识图参考 JUC框架学习顺序参考 J.U.C学习总结参考,简洁直观 易百并发编程,实践操作1,不推荐阅读,不及格 JUC文章,带例子讲解,可以学习2 Doug L ...