Download presentation
Presentation is loading. Please wait.
1
中国科学技术大学计算机系 陈香兰(0512-87161312) xlanchen@ustc.edu.cn Spring 2011
Linux操作系统分析 中国科学技术大学计算机系 陈香兰(0512- ) Spring 2011
2
程序的执行
3
操作系统是如何通过可执行文件的内容建立进程的执行上下文的?
可执行文件的格式 程序以可执行文件的形式存放在磁盘上 库 可供很多程序使用的一些例程的集合 静态库 vs 共享库 命令行参数、环境变量等 Shell提示符下输入 从shell继承而来,用户可修改
4
提纲 可执行文件 可执行格式 Exec函数
5
可执行文件 可执行文件是一个普通的文件,它描述了如何初始化一个新的进程上下文 Fork + execve
6
命令行参数和shell环境 用户使用shell来执行某个程序时,可以指定命令行参数
例如:$ ls -l /usr/bin 列出/usr/bin下的目录信息 Shell本身不限制命令行参数的个数, 命令行参数的个数受限于命令自身 例如,int main(int argc, char *argv[]) 又如, int main(int argc, char *argv[], char *envp[])
7
命令行参数和环境串都放在用户态堆栈中
8
库 源文件目标文件可执行文件 最小的程序也会利用到C库 例如:void main(void) {} 其他库
在进程结束时,杀死进程(在main的最后插入exit()) 其他库 libm,包含浮点操作的基本函数 libX11,所有X11窗口系统图形接口的基本底层函数
9
静态链接 vs 动态链接 静态库 动态链接:共享库 Gcc的-static选项指明使用静态库
10
程序段和进程的线性区 在逻辑上,Unix程序的线性地址空间被划分为各种段(segment) 在mm_struct中都有对应的字段
正文段,text 数据段,data Bss段 堆栈段 在mm_struct中都有对应的字段
11
此外,还有共享库和文件的映射,他们映射在其他线性区
参阅/proc/1/maps了解init进程的线性区
13
可执行格式 Linux标准的可执行格式 旧版的可执行文件格式 其他 ELF:Executable and Linking Format
a.out:Assembler OUT put format 其他 MS-DOS的exe文件 UNIX BSD的COFF文件
14
Linux对可执行文件格式的处理 在系统启动时,所有编译进内核的可执行格式都被注册 在系统运行过程中,也可以注册一个新的可执行文件格式
使用linux_binfmt对象管理
15
linux_binfmt 链表,连接所有linux_binfmt对象 通过读存放在可执行文件中的信息为当前进程建立一个新的进程上下文
动态的把一个共享库绑定到一个已经在运行的进程 将当前进程的上下文保存到名为core的文件中 例如
16
Linux 中看到的可执行文件格式
17
Linux通过可执行文件的扩展名或者存放在文件前128字节的magic数来识别文件格式
文件扩展名 Exe Bat …
18
Exec函数家族 用一个指定的可执行文件所描述的上下文代替进程的上 下文 系统调用:execve sys_execve
指定被执行文件的路径名 用一个指定的可执行文件所描述的上下文代替进程的上 下文 系统调用:execve sys_execve
19
do_execve open_exec bprm_mm_init search_binary_handler copy_strings_kernel & copy_strings mm_alloc __bprm_mm_init 初始化栈线性区 load_binary 对于elf格式的文件: 找到load_elf_binary 并调用它加载可执行 文件 set_brk 、elf_map、do_mmap 建立各线性区
20
举例 void main(void) {} 使用gcc –g –static参数编译
使用readelf –h获得可执行文件头,查看可执行程序的入口地址 使用objdump –D反汇编 查看入口地址所对应的程序是什么(_start) 查看从入口到main的调用路径 使用gdb来跟踪执行 在_start处设置断点,查看esp的值(验证堆栈位置在3G附近) 环境Kubuntu9.10 _start:main入口地址被压入栈中 调用__libc_start_main call *0x8(%ebp) mov %eax,(%esp) call ab0 <exit> _start:0xbffff3f0 _main:0xbffff348
21
do_execve:调用kzalloc分配struct linux_binprm数据结构,即bprm
bprm->p最开始在 __bprm_mm_init中初始化, 指向堆栈线性区的顶端相关位置 bprm->p = vma->vm_end - sizeof(void *); 此时, vma->vm_end为3G copy_strings中,会留出参数空间,例如arg,env bprm->p -= len; 关于用户态堆栈 的建立 setup_arg_pages中,继续调整 bprm->p -= stack_shift; mm->arg_start = bprm->p; remove_arg_zero中,继续调整 bprm->p++; bprm->argc--; create_elf_tables中,继续调整 bprm->p = STACK_ROUND(sp, items); start_thread中, bprm->p 传递到regs中的sp上下文中,与此同时 ip上下文指向入口地址
22
作业 什么是线性区?列举4种最常见的线性区。 Linux如何描述进程的地址空间?
按照ppt中所举的例子void main(void) {},查看反汇编代码, 若main函数有参数,则参数是如何传递给main的?
23
Thanks! The end.
Similar presentations