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 ...
随机推荐
- apply 和call 的区别,apply实用小技巧
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- Spring AOP的实现研究
1. 背景 在前文Spring IOC容器创建bean过程浅析已经介绍了Spring IOC创建初始化bean的大致过程.现在对Spring的AOP实现机制进行研究分析. 2. 名词与概念 名词 概念 ...
- centos7下安装docker(12.4容器如何与外部进行通信)
1.容器如何访问外部 前面我们做了很多试验:只要host能连外网,使用默认bridge(docker0)创建得容器就能访问外网,那么容器是怎样访问外网的呢? 注:这里的外网不仅是internet,包括 ...
- python 播放mp3
import os os.system('out1.mp3') 自动带开播放器
- day04流程控制之while
while语法: while 条件: 缩进的循环体 # 如果条件为真,那么循环体则执行,执行完毕后再次循环,重新判断条件. # 如果条件为假,那么循环体不执行,循环终止 示例一: "&qu ...
- 深入浅出的webpack构建工具---DllPlugin DllReferencePlugin提高构建速度(七)
阅读目录 一:什么是DllPlugin 和 DllReferencePlugin?作用是什么? 二:在项目中如何使用 DllPlugin 和 DllReferencePlugin? 三:DllPlug ...
- POJ2387(dijkstra堆优化)
Til the Cows Come Home Bessie is out in the field and wants to get back to the barn to get as much s ...
- ftrace利器之trace-cmd和kernelshark
关键词:ftrace.trace-cmd.kernelshark. trace-cmd是设置读取ftrace的命令行工具,kernelshark既可以记录数据,也可以图形化分析结果. trace-cm ...
- linux中断源码分析 - 初始化(二)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 本篇文章主要讲述源码中是如何对中断进行一系列的初始化的. 回顾 在上一篇概述中,介绍了几个对于中断来说非常重要的 ...
- 交换左Ctrl键和Caps lock键
Windows 10 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control ...