Linux内核分析作业第七周
一、 预处理、编译、链接
gcc hello.c -o hello.
gcc编译源代码生成最终可执行的二进制程序,GCC后台隐含执行了四个阶段步骤。
预处理 → 编译
→
汇编
→
链接
预处理:编译器将C源代码中包含的头文件编译进来和执行宏替换等工作。
gcc -E hello.c -o hello.i
编译:gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。
gcc –S hello.i –o hello.s
-S:该选项只进行编译而不进行汇编,生成汇编代码。
汇编:把编译阶段生成的.s文件
转成二进制目标代码.
gcc –c hello.s –o hello.o
链接:将编译输出.o文件
链接成最终的可执行文件。
gcc hello.o –o hello
运行:若链接没有-o指明,则生成可执行文件默认为a.out
./hello
二、可执行文件
1、在windows环境下,只要双击一个.exe的文件就可以执行一个程序,这个以.exe结尾的文件就是一个可执行文件。在andriod系统下,一个.apk的文件就是一个可执行文件,在linux系统下,可执行文件在linux环境下并没有什么特殊的后缀标记,只是在生成该文件时,它的属性设置了可执行(就是‘x’),那么他就是属于可执行文件。
2、linux系统中,可执行文件的格式为elf(Executable and Linking Format)格式
ELF文件有三种类型:
- 可重定位文件 :也就是通常称的目标文件,后缀为.o。链接器将它作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件。
- 共享文件 :这些就是所谓的动态库文件,也即 .so 文件。如果拿前面的静态库来生成可执行程序,那每个生成的可执行程序中都会有一份库代码的拷贝。如果在磁盘中存储这些可执行程序,那就会占用额外的磁盘空间;另外如果拿它们放到Linux系统上一起运行,也会浪费掉宝贵的物理内存。如果将静态库换成动态库,那么这些问题都不会出现。
- 可执行文件
- 第一个是连接编辑器,可以和其他的可重定位和共享object文件来创建其他的object。
- 第二个是动态链接器,联合一个可执行文件和其他的共享object文件来创建一个进程映象。
readelf -h
typedef struct {
Elf32_Word p_type; /* 段类型 */
Elf32_Off p_offset; /* 段位置相对于文件开始处的偏移量 */
Elf32_Addr p_vaddr; /* 段在内存中的地址 */
Elf32_Addr p_paddr; /* 段的物理地址 */
Elf32_Word p_filesz; /* 段在文件中的长度 */
Elf32_Word p_memsz; /* 段在内存中的长度 */
Elf32_Word p_flags; /* 段的标记 */
Elf32_Word p_align; /* 段在内存中对齐标记 */
}Elf32_Phdr;
4、可执行程序动态链接
(1)动态链接
load_elf_binary(...)
{
...
kernel_read();//其实就是文件解析
...
//映射到进程空间 0x804 8000地址
elf_map();//
...
if(elf_interpreter) //依赖动态库的话
{
...
//装载ld的起点 #获得动态连接器的程序起点
elf_entry=load_elf_interp(...);
...
}
else //静态链接
{
...
elf_entry = loc->elf_ex.e_entry;
...
}
...
//static exe: elf_entry: 0x804 8000
//exe with dyanmic lib: elf_entry: ld.so addr
start_thread(regs,elf_entry,bprm->p);
}
- 实际上,装载过程是一个广度遍历,遍历的对象是“依赖树”。
主要过程是动态链接器完成、用户态完成。
(2)装载时动态链接
/*准备.so文件*/
shlibexample.h (1.3 KB) - Interface of Shared Lib Example
shlibexample.c (1.2 KB) - Implement of Shared Lib Example/*编译成libshlibexample.so文件*/
$ gcc -shared shlibexample.c -o libshlibexample.so -m32/*使用库文件(因为已经包含了头文件所以可以直接调用函数)*/
SharedLibApi();
(3)运行时动态链接
dllibexample.h (1.3 KB) - Interface of Dynamical Loading Lib Example
dllibexample.c (1.3 KB) - Implement of Dynamical Loading Lib Example/*编译成libdllibexample.so文件*/
$ gcc -shared dllibexample.c -o libdllibexample.so -m32/*使用库文件*/
void * handle = dlopen("libdllibexample.so",RTLD_NOW);//先加载进来
int (*func)(void);//声明一个函数指针
func = dlsym(handle,"DynamicalLoadingLibApi");//根据名称找到函数指针
func(); //调用已声明函数
(4)运行
$ gcc main.c -o main -L/path/to/your/dir -lshlibexample -ldl -m32
$ export LD_LIBRARY_PATH=$PWD
/*将当前目录加入默认路径,否则main找不到依赖的库文件,当然也可以将库文件copy到默认路径下。*/
三、可执行程序的装载
1、sys_execve内核处理过程
(1)新的可执行程序
- 一般是地址空间为0x8048000或0x8048300
(2)execve与fork
- execve和fork都是特殊一点的系统调用:一般的都是陷入到内核态再返回到用户态。
- fork两次返回,第一次返回到父进程继续向下执行,第二次是子进程返回到ret_from_fork然后正常返回到用户
- execve执行的时候陷入到内核态,用execve中加载的程序把当前正在执行的程序覆盖掉,当系统调用返回的时候也就返回到新的可执行程序起点。
(3)execve
- 执行到可执行程序 -> 陷入内核
- 构造新的可执行文件 -> 覆盖掉原可执行程序
- 返回到新的可执行程序,作为起点(也就是main函数)
- 需要构造其执行环境;
Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数,先函数调用参数传递,再系统调用参数传递。
(4)静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时不同
- 静态链接:elf_entry指向可执行文件的头部,一般是main函数,是新程序执行的起点。
- 动态链接:elf_entry指向ld(动态链接器)的起点,加载load_elf_interp
1、在实验楼虚拟机下,键入以下指令更新 MenuOS
cd LinuxKernel
rm menu -rf
git config --global user.name "Scott Chacon"
git config --global user.mail "schacon@gmail.com"
git clone https://github.com/mengning/menu.git
cd menu
mv test_exec.c test.c
make rootfs
3、以跟踪模式启动MenuOS
关闭 MenuOS,以如下指令重启 MenuOS:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
水平分割终端模拟器窗口,运行gdb,让 MenuOS 完全启动,处于接收命令状态:
cd ~/LinuxKernel
gdb
(gdb) file linux-3.18.6/vmlinux
(gdb) target remote:1234
(gdb) c # 让 MenuOS 完全启动,处于接收命令状态
按“Ctrl +C", 让 gdb 处于 gdb 命令行模式,设置断点
Linux内核分析作业第七周的更多相关文章
- 《Linux内核分析》第七周学习总结
<Linux内核分析>第七周学习总结 ——可执行程序的装载 姓名:王玮怡 学号:20135116 一.理论部分总结 (一)可执行程序的装载 ...
- 《Linux内核分析》第七周学习笔记
<Linux内核分析>第七周学习笔记 可执行程序的装载 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/co ...
- 《Linux内核分析》第七周: 可执行程序的装载
LINUX内核分析第七周学习总结--可执行程序的装载 杨舒雯(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...
- 《Linux内核分析》第七周 可执行程序的装载
[刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK SEVEN ...
- 《Linux内核分析》第七周笔记 可执行程序的装载
20135132陈雨鑫 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ...
- 《Linux内核分析》第七周学习总结 可执行程序的装载
第七周.可执行程序的装载 一.可执行程序是如何产生的? (1).c文件gcc汇编形成.s和.asm汇编代码: (2)汇编代码经过gas变成.o目标文件: (3)目标文件变成可执行文件: (4)可执行文 ...
- Linux内核分析作业第五周
系统调用的三个层次(下) 一.给MenuOS增加time和time-asm命令 1.克隆并自动编译 MenuOS rm menu -rf 强制删除原menu文件 git clone https://g ...
- Linux内核分析(第七周)
可执行程序的装载 一.预处理.编译.链接和目标文件的格式 1.可执行程序怎么来的? 预处理: gcc -E -o hello.cpp hello.c -m32 *负责把include的文件包含进来及宏 ...
- Linux内核分析作业第三周
一.实验楼实验 使用实验楼的虚拟机打开shell 1 cd LinuxKernel/ 2 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd ...
随机推荐
- 路由交换01-----ICMP协议
路由交换协议------ICMP ICMP协议 ICMP (InternetControl Message Protocol)协议是TCP/IP协议簇的核心协议之一,用来在网络设备之间传递各种差错和控 ...
- Static简介
1.static称为静态修饰符,它可以修饰类中得成员.被static修饰的成员被称为静态成员,也成为类成员,而不用static修饰的成员称为实例成员. 2.当 Voluem volu1 = new V ...
- P1056 排座椅
非原创 #include<bits/stdc++.h>using namespace std;int t1[2009];int t2[2009]; int findmax(int *a){ ...
- WPF之托盘图标的设定
首先需要在项目中引用System.Windows.Forms,System.Drawing; using System; using System.Collections.Generic; using ...
- 离线安装Cloudera Manager 5和CDH5(最新版5.9.3) 完全教程(七)界面安装
一.安装过程 1.1 登录 1.2 接受许可协议 1.3 选择免费版本 1.4 选择下一步 1.5 选择当前管理的主机 1.6 选择使用Parcel安装,选择CDH版本,点击继续 1.7 等待安装 此 ...
- logbak 配置相关
一.配置简单 1. 配置简单,易于上手,通过logback.xml文件进行配置,如果没有配置的话,执行默认配置 <configuration> <appender name=&quo ...
- 深入理解mybatis原理, Mybatis初始化SqlSessionFactory机制详解(转)
文章转自http://blog.csdn.net/l454822901/article/details/51829785 对于任何框架而言,在使用前都要进行一系列的初始化,MyBatis也不例外.本章 ...
- PAT A1099 Build A Binary Search Tree (30 分)——二叉搜索树,中序遍历,层序遍历
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...
- docker执行第一个应用
概念科普 Docker image:镜像是只读的,镜像中包含有需要运行的文件.镜像用来创建container,一个镜像可以运行多个container:镜像可以通过Dockerfile创建,也可以从Do ...
- AI 深度生成模型
深度生成模型 1.玻尔兹曼机