栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

2021-2022-1 20212808 《Linux内核原理与分析》第八周作业

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2021-2022-1 20212808 《Linux内核原理与分析》第八周作业

Linux内核的实质和Linux系统的一般执行过程 ELF目标文件格式
  • 目标文件(ABI,应用程序二进制接口):编译器生成的文件。
  • 目标文件的格式:out格式、COFF格式、PE(windows)格式、ELF(Linux)格式。
  • ELF(Executable and linkable Format)即可执行和可链接的格式,是一个目标文件格式的标准。ELF格式的文件用于存储Linux程序。其包含了以下三类:
  1. 可重定位文件:保存着代码和适当的数据,用来和其它的目标文件一起来创建一个可执行文件、静态库文件或者是一个共享目标文件
  2. 可执行文件:保存着一个用来执行的程序,一般由多个可重定位文件结合生成,是完成了所有重定位工作和符号解析(除了运行时解析的共享库符号)的文件。
  3. 共享目标文件:保存着代码和合适的数据,用来被两个链接器链接。第一个是链接编辑器(静态链接),可以和其它的可重定位和共享目标文件来创建其它的object。第二个是动态链接器,联合一个可执行文件和其它的共享目标文件来创建一个进程映象。
  • 程序从源代码到可执行文件的步骤:预处理、编译、汇编、链接
    ①编译器预处理:gcc -E -o XX.cpp XX.c (-m32)
    ②汇编器编译成汇编代码
    gcc -x cpp-output -S -o hello.s hello.cpp (-m32)
    ③汇编代码编译成二进制目标文件
    gcc -x assembler -c hello.s -o hello.o (-m32)
    ④链接成可执行文件
    gcc -o hello.static hello.c (-m32) -static

    预处理和编译完的文件均为文本文件,汇编和链接完的文件均为ELF文件。
  • 可执行文件处理过程也是系统调用。
  • 程序装载中fork与execve的区别和联系
  1. 他们都是比较特殊的系统调用
  2. fork在陷入内核态后有两次返回,第一次返回到原来父进程的位置继续向下执行,第二次是在子进程返回,这次会返回到ret_from_fork,之后正常返回用户态。
  3. execve在执行时陷入内核态,在内核中调用execve加载的可执行文件把当前进程的可执行程序给覆盖了,当其返回时,返回的已经不是原来的那个可执行程序了,而是新的程序,返回的是新的可执行程序执行的起点,即main函数的大致位置(一般地址为0x8048xxx,由编译器设定)。
  4. ELF可执行文件总是被映射到0x8048000这个地址。
  • 链接,从过程上讲:符号解析、重定位。根据链接时机:静态链接、动态链接。编译器默认使用动态链接,动态链接分为两种:可执行程序装载时动态链接、运行时动态链接。动态链接库实际上是一个图的遍历,装载和链接之后将CPU的控制权交给可执行程序。
实验七: 一、 编程使用exec* 库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接,编程练习动态链接库的这两种使用方式。

1.准备好代码,编译成libshlibexample.so,libdllibexample.so文件

$ gcc -shared shlibexample.c -o libshlibexample.so 
$ gcc -shared dllibexample.c -o libdllibexample.so 


2. main函数中分别以共享库和动态加载共享库的方式使用libshlibexample.so文件和libdllibexample.so文件
3. 动态衔接运行测试,使用参数-L表明文件路径,-l表示库文件名。(这部分之前练习过,当复习一遍了)

gcc main.c -o main -L./ -l shlibexample -ldl -m32
export LD_LIBRARY_PATH=$PWD
./main

二、使用gdb跟踪execve系统调用内核处理函数sys_execve
  1. 进入LinuxKernel目录,删除menu目录,克隆一个新的menu
  2. 进入menu目录,用make rootfs对覆盖后新文件进行编译、自动生成根文件系统。新增了exec系统调用,在MenuOS输入help查询系统调用函数,测试新加入的exec命令。
  3. 启动qemu,并加载内核和端口。
  4. 水平分割启动gdb,设置sys_execve和load_elf_binary和start_thread三个断点,按“c”继续执行到sys_exec时输入exec命令,结果运行停在sys_exec。


5. new_ip是返回到用户态的第一条指令,退出调试。
输入redelf -h hello可以查看hello的EIF头部,可以看到定义的入口地址与“new_ip”所指向的地址一致。

exec()函数代码分析

do_ execve调用do_ execve_ common,do_ execve_ common主要依靠exec_ binprm。在exec_ binprm中又有一个至关重要的函数,叫做search_binary_ handler。这就是sys_execve的内部处理过程。

int do_execve(struct filename *filename,
    const char __user *const __user *__argv,
    const char __user *const __user *__envp)
{
    return do_execve_common(filename, argv, envp);
}
 
 
static int do_execve_common(struct filename *filename,
                struct user_arg_ptr argv,
                struct user_arg_ptr envp)
{
    // 检查进程的数量限制
 
    // 选择最小负载的CPU,以执行新程序
    sched_exec();
 
    // 填充 linux_binprm结构体
    retval = prepare_binprm(bprm);
 
    // 拷贝文件名、命令行参数、环境变量
    retval = copy_strings_kernel(1, &bprm->filename, bprm);
    retval = copy_strings(bprm->envc, envp, bprm);
    retval = copy_strings(bprm->argc, argv, bprm);
 
    // 调用里面的 search_binary_handler
    retval = exec_binprm(bprm);
 
    // exec执行成功
 
}
 
static int exec_binprm(struct linux_binprm *bprm)
{
    // 扫描formats链表,根据不同的文本格式,选择不同的load函数
    ret = search_binary_handler(bprm);
    // ...
    return ret;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/468277.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号