2019-2020-1 20199314 《Linux内核原理与分析》 第八周作业
可执行程序工作原理、
1、ELF(Executable and Linkable Format)可执行和可链接文件,其包含了以下三类:
- 可重定位文件(Relocatable File):保存着代码和适当的数据,用来和其它的目标文件一起来创建一个可执行文件、静态库文件或者是一个共享目标文件(主要是.o文件)
- 可执行文件(Executable File):保存着一个用来执行的程序,一般由多个可重定位文件结合生成,是完成了所有重定位工作和符号解析(除了运行时解析的共享库符号)的文件。
- 共享目标文件(Shared Object File):保存着代码和合适的数据,用来被两个链接器链接。第一个是链接编辑器(静态链接),可以和其它的可重定位和共享目标文件来创建其它的object。第二个是动态链接器,联合一个可执行文件和其它的共享目标文件来创建一个进程映象。
2、ELF文件格式:
ELF文件的主体是各种节,以及描述这些节属性的信息(Program header table和 Section header table),以及ELF文件的整体性信息(ELF header),如下图。
3、程序编译
程序从源代码到可执行文件的步骤:预处理、编译、汇编、衔接--以hello.c为例。
预处理: gcc -E hello.c -o hello.i -m32
编译:gcc -S hello.i -o hello.s -m32
汇编:gcc -c hello.s -o hello.o -m32
默认衔接(动态库):gcc hello.o -o hello -m32
衔接静态库:gcc hello.o -o hello.static -m32 -static
最后得到的hello和hello-static文件就是可执行文件。可执行文件中的内容包括有编译后的机器指令代码、数据还包括了链接时所须要的一些信息,比如符号表、调试信息、字符串等。
其文件格式,如下图。
4、静态衔接和动态衔接
静态链接:在编译链接时直接将需要的执行代码复制到最终可执行文件中,优点是代码的装载速度快,执行速度也比较快,对外部环境依赖度低。缺点是如果多个应用程序使用同一库函数,会被装载多次,浪费内存。
动态链接:编译时不直接复制可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统。操作系统负责将需要的动态库加载到内存中,在程序运行到指定的代码时,去共享执行内存中已经加载的动态库去执行代码,最终达到运行时链接的目的。优点是多个程序可以共享同一段代码,而不需要在磁盘上存储多个复制。缺点是在运行时加载可能会影响程序的前期执行性能,而且对使用的库依赖性较高。(分为装载时动态链接和运行时动态链接)
使用gcc hello.o -o hello.static -static进行静态链接,发现得到的可执行程序文件大小可达到动态链接的100倍,如图。
5、动态衔接
动态衔接分为以下两种;
- 可执行程序装载时动态衔接
2.运行时动态衔接。
装载时动态衔接意味着在程序一开始启动的时候其所调用的库需要在一开始就提供,而运行时动态衔接只有程序运行到相关语句才会访问dllibexample。
6、fork和execve区别与联系
对于fork():
1、子进程复制父进程的所有进程内存到其内存地址空间中。父、子进程的
“数据段”,“堆栈段”和“代码段”完全相同,即子进程中的每一个字节都
和父进程一样。
2、子进程的当前工作目录、umask掩码值和父进程相同,fork()之前父进程
打开的文件描述符,在子进程中同样打开,并且都指向相同的文件表项。
3、子进程拥有自己的进程ID。
对于exec():
1、进程调用exec()后,将在同一块进程内存里用一个新程序来代替调用
exec()的那个进程,新程序代替当前进程映像,当前进程的“数据段”,
“堆栈段”和“代码段”背新程序改写。
2、新程序会保持调用exec()进程的ID不变。
3、调用exec()之前打开打开的描述字继续打开(好像有什么参数可以令打开
的描述字在新程序中关闭)
实验1:
编程使用exec* 库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接,编程练习动态链接库的这两种使用方式。
1、实验楼上说要从某个网站上下载下面两个源码:
shlibexample.h (1.3 KB) - Interface of Shared Lib Example
shlibexample.c (1.2 KB) - Implement of Shared Lib Example
但是后来查到是网易云付费课的附件,为了两个代码没必要花这么多钱,再说书上已经有源码了,可以自己写一遍,但是书上的代码有一个大坑,直接影响了我后面做实验的进度,之后来我会说明。
shlibexample.h
#ifndef _SH_LTB_EXAMPLE_H_
#define _SH_LTB_EXAMPLE_H_
#define SUCCESS 0
#define FAILURE (-1)
#ifdef __cplusplus
extern "C" {
#endif
int SharedLibApi();
#ifdef __cplusplus
}
#endif
#endif
dllibexample.h
#ifndef _DL_LTB_EXAMPLE_H_
#define _DL_LTB_EXAMPLE_H_
#ifdef _cplusplus
extern "C"{
#endif
int DynamicalLoadingLibApi();
#ifdef _cplusplus
}
#endif
#endif
shlibexample.c
#include <stdio.h>
#include "shlibexample.h"
int SharedLibApi()
{
printf("This is a shared libary!\n");
return SUCCESS;
}
dllibexample.c
#include <stdio.h>
#include "dllibexample.h"
#define SUCCESS 0
#define FAILURE(-1)
int DynamicalLoadingLibApi()
{
printf(“This is a Dynamical Loading library”!\n”);
return SUCCESS;
}
2、编译成libshlibexample.so文件
$ gcc -shared shlibexample.c -o libshlibexample.so -m32
$ gcc -shared dllibexample.c -o libdllibexample.so -m32
错误到这里就显现出来了,为什么会报错我在网上查了很多答案,什么需要更新gcc啊,什么C文件头名字冲突啊,反正各种答案,耗费了很久时间就是依旧会报错,于是我重新打了好几遍代码,直到发现有一个贼细小的地方,书上很容易误导。
**注意看!这分明看着是就是LIB对吧,我在vim编辑器中敲的时候也和书上的样子差不多,然而我仔细看了一下I的上横和下横还是有点长短不一的,这货该不会是T吧!!,结果事实验证了我的判断,这货就是T,LTB。终于找到原因了 **
3、mian函数中分别以共享库和动态加载共享库的方式使用libshlibexample.so文件和libdllibexample.so文件
main.c
#include <stdio.h>
#include "shlibexample.h"
#include <dlfcn.h>
int main()
{
printf("This is a Main program!\n");
/* Use Shared Lib */
printf("Calling SharedLibApi() function of libshlibexample.so!\n");
SharedLibApi(); //直接调用共享库
/* Use Dynamical Loading Lib */
void * handle = dlopen("libdllibexample.so",RTLD_NOW);//打开动态库并将其加载到内存
if(handle == NULL)
{
printf("Open Lib libdllibexample.so Error:%s\n",dlerror());
return FAILURE;
}
int (*func)(void);
char * error;
func = dlsym(handle,"DynamicalLoadingLibApi");
if((error = dlerror()) != NULL)
{
printf("DynamicalLoadingLibApi not found:%s\n",error);
return FAILURE;
}
printf("Calling DynamicalLoadingLibApi() function of libdllibexample.so!\n");
func();
dlclose(handle); //卸载库
return SUCCESS;
}
4、动态衔接运行测试
因为shilibexample在衔接时就需要提供路径,对应的头文件shilibexample.h也需要在编译器能找到位置。使用参数-L表明文件路径,-l表示库文件名。
dllibexample只有在程序运行到相关语句才会访问,在编译时不需要任何的相关信息,使用-ldl指明其所需要的共享库dlopen,同时修改LD_LIBRARY_PATH确保dllibexample.so可以查到。
gcc main.c -o main -L./ -l shlibexample -ldl -m32
export LD_LIBRARY_PATH=$PWD
./main
实验2:
使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve ,验证您对Linux系统加载可执行程序所需处理过程的理解。
实验二就只能在实验楼环境做了,毕竟本地虚拟机没有配好的环境。
1、首先从github上下载包含test_exec.c文件的文件夹,进行编译。
ls
cd ~/LinuxKernel
rm menu -rf
git clone https://github.com/mengning/menu.git
cd menu
mv test_exec.c test.c
make rootfs
2、在qemu界面使用help和exec命令查看是否编译成功。
3、随后重新启动qemu。
4、加载内核和端口。
5、设置三个断点。
6、调试运行程序。
2019-2020-1 20199314 《Linux内核原理与分析》 第八周作业的更多相关文章
- 2019-2020-1 20199329《Linux内核原理与分析》第九周作业
<Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...
- 2019-2020-1 20199329《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...
- 20169212《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...
- 20169210《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业
2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...
- 2017-2018-1 20179215《Linux内核原理与分析》第二周作业
20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...
- 2019-2020-1 20209313《Linux内核原理与分析》第二周作业
2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...
- 2018-2019-1 20189221《Linux内核原理与分析》第一周作业
Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...
- 《Linux内核原理与分析》第一周作业 20189210
实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...
- 2018-2019-1 20189221《Linux内核原理与分析》第二周作业
读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...
随机推荐
- 编程小技巧之 Linux 文本处理命令
合格的程序员都善于使用工具,正所谓君子性非异也,善假于物也.合理的利用 Linux 的命令行工具,可以提高我们的工作效率. 本文简单的介绍三个能使用 Linux 文本处理命令的场景,给大家开阔一下思路 ...
- mac下安装jmeter
jmeter官网下载 双击解压 命令行进入/Users/yanguobin/apache-jmeter-5.1.1/bin目录下,输入sh jmeter即可启动 也可以 配置环境变量 vim ~/.b ...
- 关于人工智能和python
人工智能的话题在近几年可谓是相当火热,前几天看快本时其中有一个环节就是关于人工智能的,智能家电.智能机器人.智能工具等等,在我的印象里,提到人工智能就会出现 Python,然后我便在网上查找了相关信息 ...
- 我们一起学Python之——认识Python"规则"
前言: 开学后,跟预想的一样,开学第一天我们就开了Python,虽然之前早就预料到了,但对于一直学Java的我来说,内心还是有一些涟漪的.总归还是要接受的,还不如振作起来,认真对待.我决定从最简单并且 ...
- 动态扩容lvm逻辑卷的操作记录
在进行动态扩容LVM逻辑卷的之前,先看这篇文章:https://www.cnblogs.com/huhyoung/p/9689776.html.以下是我实操记录. 在上班期间,测试经理突然找我,能不能 ...
- python 报错TypeError: 'range' object does not support item assignment,解决方法
贴问题 nums = range(5)#range is a built-in function that creates a list of integers print(nums)#prints ...
- Flask-wtforms类似django中的form组件
一.安装 pip3 install wtforms 二.简单使用 1.创建flask对象 from flask import Flask, render_template, request, redi ...
- 解决 canvas 将图片转为base64报错: Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasEleme...
问题描述 当用户点击分享按钮时,生成一张海报,可以保存图片分享到朋友圈,用户的图片是存储在阿里云的OSS,当海报完成后,执行.canvas.toDataURL("image/png" ...
- 第3章(1) Linux内核相关概念
Linux内核的组成 1. Linux内核源代码的目录结构 arch:包含和硬件体系结构相关的代码,每种平台占一个相应的目录,如 i386.arm. arm64.powerpc.mips 等.Linu ...
- 致远OA_0day批量植Cknife马一步到位
最近各位师傅都在刷这个嘛,原本的exp是上传一个test123456.jsp的命令执行的马子,不过我在试的时候发现替换成C刀一句话出错,原因未知,并且test123456.jsp如果存在的话用原来ex ...