zoukankan      html  css  js  c++  java
  • 20179223《Linux内核原理与分析》第八周学习笔记

    视频学习

    可执行文件是怎么得来的?

    .c汇编成汇编代码.asm,然后再汇编成目标码.o。然后在连接成可执行文件,然后加载到内存可执行了。

    对hello.c文件预处理(cpp),预处理负责把include的文件包含进来及宏替换等工作。
    把hello.cpp编译成汇编代码hello.s
    再把编译代码hello.s编译成目标代码hello.o(二进制的文件),然后把hello.o链接成可执行文件hello。
    hello是使用共享库的,再静态编译,把所有完全依赖的都放在hello.static的内部。

    目标文件的格式ELF

    一个可重定位(relocateble)文件保存着代码和适当的数据,用来和其他的object文件一起来创建一个可执行文件或者是一个共享文件。

    一个可执行(executable)文件保存着一个用来执行的程序;该文件指出了exec(BA_OS)如何来创建程序进程映像。

    一个共享object文件保存着代码和合适的数据,用来被下面的两个链接器链接。第一个是连接编辑器,可以和其他的可重定位和共享object文件来创建其他的object。第二个是动态链接器,联合一个可执行文件和其他的共享object文件来创建一个进程映象。

    Object文件与程序的连接(创建一个程序)和程序的执行(运行一个程序)

    一个ELF头文件的开始,保存了路线图(road map),描述了该文件的组织情况程序头表(program header table)告诉系统如何来创建一个进程的内存映象。section头表(section header table)包含了描述文件sections的信息。每个section在这个表中有一个入口,每个入口给出了该section的名字,大小,等等信息。

    当创建或增加一个进程映象的时候,系统在理论上将拷贝一个文件的段到一个虚拟的内存段。

    静态链接的ELF可执行文件与进程的地址空间

    可执行文件加载到内存中开始执行的第一行代码。

    一半静态链接将所有代码放在一个代码段。

    动态链接的进程有多个代码段。

    装载可执行程序之前的工作

    可执行程序的执行环境

    命令行参数和shell环境,一般我们执行一个程序的shell环境,我们的实验直接使用execve系统调用。

    $ ls -l /usr/bin 列出usr/bin下的目录信息
    Shell本身不限制命令行参数的个数,命令行参数的个数受限于命令自身
    ——例如,int main(int argc, charargv[])
    ——又如,int main(int argc, char
    argv[], charenvp[])
    Shell会调用execue将命令行参数和环境参数传递给可执行程序的main函数
    ——int execve(const char
    filename,charconst argv[],charconst envp[]);
    ——库函数exec*都是execue的封装例程

    sys_execve内部会解析可执行文件格式
    do_execve -> do_execve_common -> exec_binprm
    search_binary_handler符合寻找文件格式对应的解析模块
    对于ELF格式的可执行文件fmt->load_binary(bprm);执行的应该是load_elf_binary其内部是和ELF文件格式解析的部分需要和ELF文件格式标准结合起来阅读

    装载时动态链接和运行时动态链接应用举例

    动态链接分为可执行程序装载时动态链接和运行时动态链接

    编译成libshlibexample.so文件

    $ gcc -shared shlibexample.c -o libshlibeexample.so -m32
    

    这就生成了一个共享库文件,共享库和动态加载共享库内部定义其实是一样的

    编译main,注意这里只提供shlibexample的-L(库对应的接口头文件所在目录)和-l(库名,如libshlibexample.so去掉lib和.so的部分)并没有提供dllibexample的相关信息,只是指明了-ldl

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

    -L指明当前目录, -l指明这个库文件,-ldl动态加载器

    可执行程序的装载相关关键问题分析

    execve和fork都是特殊一点的系统调用,子进程是从ret_from_fork开始执行然后返回用户态

    使用GDB跟踪sys_execve内核函数的处理过程

    搭配环境,删除旧的menu目录,重新下载新的版本,test.c覆盖test_exec.c 操作如下:

    $ cd LinuxKernel
    $ rm menu -rf
    $ git clone http://github.com/mengning/menu.git
    $ cd menu
    $ mv test_exec.c test.c
    

    重新编译并启动程序:

    $ make rootfs
    

    使用qemu命令重新启动内核并使用-s和-S参数“冻结”系统执行,命令如下:

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

    此时为了使用gdb进行调试,需要水平分割一个窗口,输入如下命令:

    $ gdb
    (gdb) file linux-3.18.6/vmlinux
    (gdb) target remote:1234
    

    设置断点sys_execve和load_elf_binary还有start_thread。

    执行之后进入了系统调用SyS_execve

    跟踪,继续执行进入load_elf_binary

    继续跟踪,进入到start_thread

    new_ip是返回到用户态的第一条指令的地址

    课本第13,14章知识学习

    虚拟文件系统中(VFS)有四个主要的对象类型:

    1.超级块对象:代表一个具体的已安装文件系统;

    2.索引节点对象:代表一个具体文件;

    3.目录项对象:代表一个目录项,是路径的一个组成部分;

    4.文件对象:代表由进程打开的文件

    四种I/O调度程序:

    1.Linus电梯。能执行合并与排序预处理;

    2.最终期限I/O调度程序。为解决请求饥饿问题;

    3.完全公正的排队I/O调度程序。以时间片轮转调度队列;

    4.空操作的I/O调度程序。专为随机访问设备而设计的。

  • 相关阅读:
    阿里P8架构师谈:阿里双11秒杀系统如何设计?
    秒杀系统设计的知识点
    秒杀系统架构优化思路
    秒杀系统解决方案
    Entity Framework Code First (七)空间数据类型 Spatial Data Types
    Entity Framework Code First (六)存储过程
    Entity Framework Code First (五)Fluent API
    Entity Framework Code First (四)Fluent API
    Entity Framework Code First (三)Data Annotations
    Entity Framework Code First (二)Custom Conventions
  • 原文地址:https://www.cnblogs.com/9223lx/p/7844972.html
Copyright © 2011-2022 走看看