陈巧然原创作品 转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-100002900

实验目的

使用gdb跟踪sys_execve内核函数的处理过程,分析exec*函数对应的系统调用处理过程,理解Linux内核如何装载和启动一个可执行程序。

实验过程

登陆实验楼虚拟机http://www.shiyanlou.com/courses/195

打开shell终端,执行以下命令:

cd LinuxKernel

rm -rf menu

git clone https://github.com/mengning/menu.git

cd menu

mv test_exec.c test.c

make rootfs

可以看到启动后的MenuOS已经包含了exec命令。

可以通过增加-s -S启动参数打开调试模式

qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S

打开gdb进行远程调试

gdb

file ../linux-3.18.6/vmlinux

target remote:1234

设置断点

b sys_execve

b do_execve

b do_execve_common

b exec_binprm

b search_binary_handler

b load_elf_binary

b start_thread

实验分析

通过查看源码可以看出执行exec命令是通过调用execlp函数实现的,属于库函数exec*都是execve的封装例程。

装载和启动一个可执行程序依次调用以下函数:

sys_execve() -> do_execve() -> do_execve_common() -> exec_binprm() -> search_binary_handler() -> load_elf_binary() -> start_thread()

实验总结

当linux内核或程序(例如shell)用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序。

当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。

因为调用exec并不创建新进程,所以前后的进程ID并未改变。

exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈段。

参考资料:《UNIX环境高级编程第二版》

学习笔记

程序编译链接过程

预处理:(.c -> .cpp)

gcc -E -o hello.cpp hello.c -m32

编译:(.cpp -> .s 汇编)

gcc -x cpp-output -S -o hello.s hello.cpp -m32

编译:(.s -> .o 二进制目标代码)

gcc -x assembler -c hello.s -o hello.o -m32

链接:(.o -> a.out)共享库

gcc -o hello hello.o -m32

静态编译:

gcc -o hello.static hello.o -m32 -static

c语言main函数格式:

int main(int argc, char *argv[])

int main(int argc, char *argv[], char *envp[])

库函数exec*都是execve的封装例程

execve函数格式:

int execve(const char * filename,char * const argv[ ],char * const envp[ ])

sys_execve -> do_execve -> do_execve_common ->  exec_binprm

说是exec系统调用,实际上在Linux中,并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是:

int execl(const char *path, const char *arg, ...);

int execv(const char *path, char *const argv[]);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execve(const char *path, char *const argv[], char *const envp[]);

int execlp(const char *file, const char *arg, ...);

int execvp(const char *file, char *const argv[]);

其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。

区别一:前4个取路径名作为参数,后2个取文件名作为参数;

区别二:参数表的传递(l表示list,v表示vector);

区别三:向新程序传递环境表。

动态链接:

装载时动态链接

gcc -shared shlibexample.c -o libshlibexample.so -m32

运行时动态链接

gcc -shared dllibexample.c -o libdllibexample.so -m32

主调程序

gcc main.c -o main -L /path/to/your/dir-l shlibexample -ldl -m32

Linux内核设计第七周学习总结 Linux内核如何装载和启动一个可执行程序的更多相关文章

  1. Linux内核分析第七周学习笔记——Linux内核如何装载和启动一个可执行程序

    Linux内核分析第七周学习笔记--Linux内核如何装载和启动一个可执行程序 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study. ...

  2. Linux内核设计第七周 ——可执行程序的装载

    Linux内核设计第七周 ——可执行程序的装载 第一部分 知识点总结 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 编译链接的过程 预处理阶段 gcc -E -o XX.cpp ...

  3. LINUX内核分析第七周学习总结:可执行程序的装载

    LINUX内核分析第七周学习总结:可执行程序的装载 韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

  4. LINUX内核分析第七周学习总结

    LINUX内核分析第七周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...

  5. LINUX内核分析第七周学习总结——可执行程序的装载

    LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

  6. 20135323符运锦----第七周:Linux内核如何装载和启动一个可执行程序

    可执行程序的装载 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 ①编译器预处理 gcc -E -o XX.cpp XX.c (-m32)// 注:把include的文件包含进来, ...

  7. linux内核分析 第七周 Linux内核如何装载和启动一个可执行程序

    一.编译链接的过程和ELF可执行文件格式 vi hello.c gcc -E -o hello.cpp hello.c -m32 //预处理.c文件,预处理包括把include的文件包含进来以及宏替换 ...

  8. 作业七:Linux内核如何装载和启动一个可执行程序

    作业七:Linux内核如何装载和启动一个可执行程序 一.编译链接的过程和ELF可执行文件格式 可执行文件的创建——预处理.编译和链接 在object文件中有三种主要的类型. 一个可重定位(reloca ...

  9. 实验七:Linux内核如何装载和启动一个可执行程序

    原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 题目自拟,内容围绕对Linu ...

随机推荐

  1. 【LeetCode算法题库】Day5:Roman to Integer & Longest Common Prefix & 3Sum

    [Q13] Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Valu ...

  2. 基于神念TGAM的脑波小车(4)

    我使用的是HC05和BT06俩个蓝牙模块 1.[AT模式]HC05蓝牙模块的PIO11接VCC,上电后即进入HC05AT指令模式,对于BT06蓝牙直接上电进入AT模式,用USBT06转TTL模块连接到 ...

  3. MyCat安装与测试教程 超详细!

    MyCat安装与测试教程 超详细! MyCat基础知识 一.什么是MYCAT? 1. 一个彻底开源的,面向企业应用开发的大数据库集群 2. 支持事务.ACID.可以替代MySQL的加强版数据库 3. ...

  4. Spark计算模型RDD

    RDD弹性分布式数据集 RDD概述 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行 ...

  5. zookeeper_节点数据版本号问题

    转自:Simba_cheng 更新节点数据的方法: 同步方法:Stat setData(final String path, byte data[], int version) 异步方法:void s ...

  6. 论文笔记:分形网络(FractalNet: Ultra-Deep Neural Networks without Residuals)

    FractalNet: Ultra-Deep Neural Networks without Residuals ICLR 2017 Gustav Larsson, Michael Maire, Gr ...

  7. Kubernetes探索学习005--Kubernetes的Controller模型和ReplicaSet伸缩

    1.Kubernetes的controller pattern 需要认识到Kubernetes操作Pod的逻辑,都是由控制器来完成的. 查看之前写过的nginx-deployment的YAML文件 [ ...

  8. kafka handler

    1.配置kafka 参数文件 在ogg主目录下有示例文件: [root@WH0PRDBRP00AP0013 ogg]# cd AdapterExamples/big-data/kafka/ [root ...

  9. linux获得命令使用帮助

    1. 内部命令: help CMD 2. 外部命令: CMD --help 3. 命令手册: manual(所有命令) man CMD 分章节: 1: 用户命令(User Commands - /bi ...

  10. 【Alpha】阶段第十次Scrum Meeting

    [Alpha]阶段第十次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 登出接口 编写后端说明文档 赵智源 编写脚本实现测试的持续集成 前测试点页面跳转逻辑测试 ...