zoukankan      html  css  js  c++  java
  • 可执行程序加载到内存的过程

    http://blog.csdn.net/q_l_s/article/details/52594252

    在linux中,程序的加载,涉及到两个工具,linker 和loader。Linker主要涉及动态链接库的使用,loader主要涉及软件的加载。

    1、  exec执行一个程序

    2、  elf为现在非常流行的可执行文件的格式,它为程序运行划分了两个段,一个段是可以执行的代码段,它是只读,可执行;另一个段是数据段,它是可读写,不能执行。

    3、  loader会启动,通过mmap系统调用,将代码端和数据段映射到内存中,其实也就是为其分配了虚拟内存,注意这时候,还不占用物理内存;只有程序执行到了相应的地方,内核才会为其分配物理内存。

    4、  loader会去查找该程序依赖的链接库,首先看该链接库是否被映射进内存中,如果没有使用mmap,将代码段与数据段映射到内存中,否则只是将其加入进程的地址空间。这样比如glibc等库的内存地址空间是完全一样。

    因此一个2M的程序,执行时,并不意味着为其分配了2M的物理内存,这与其运行了的代码量,与其所依赖的动态链接库有关。

    运行过程中链接动态链接库与编译过程中链接动态库的区别。

    我们调用动态链接库有两种方法:一种是编译的时候,指明所依赖的动态链接库,这样loader可以在程序启动的时候,来所有的动态链接映射到内存中;一种是在运行过程中,通过dlopen和dlfree的方式加载动态链接库,动态将动态链接库加载到内存中。

    这两种方式,从编程角度来讲,第一种是最方便的,效率上影响也不大,在内存使用上有些差别。

    第一种方式,一个库的代码,只要运行过一次,便会占用物理内存,之后即使再也不使用,也会占用物理内存,直到进程的终止。
    第二中方式,库代码占用的内存,可以通过dlfree的方式,释放掉,返回给物理内存。

    这个差别主要对于那些寿命很长,但又会偶尔调用各种库的进程有关。如果是这类进程,建议采用第二种方式调用动态链接库。

    mmap()和vma相关和底层的驱动相关

    如果用户的空间映射到虚拟内存大块的映射 用mmap

    驱动需要做一个简单的线性的设备内存映射, 到一个用户地址空间, remap_pfn_range 几乎是所有你做这个工作真正需要做的. 下列的代码从 drivers/char/mem.c 中得来, 并且显示了这个任务如何在一个称为 simple ( Simple Implementation Mapping Pages with Little Enthusiasm)的典型模块中进行的.

    static int simple_remap_mmap(struct file *filp, struct vm_area_struct *vma) 
    {
     if (remap_pfn_range(vma, vma->vm_start, vm->vm_pgoff,
     vma->vm_end - vma->vm_start,
     vma->vm_page_prot))
     return -EAGAIN;
     vma->vm_ops = &simple_remap_vm_ops;
     simple_vma_open(vma);
     return 0; 
    } 
    

    如你所见, 重新映射内存只不过是调用 remap_pfn_rage 来创建必要的页表.

  • 相关阅读:
    怎样用HTML5 Canvas制作一个简单的游戏
    js面向对象
    javascript闭包
    javascript变量的作用域
    5-22
    5-23
    14-5-21 硬代码
    14-5-19 类和对象
    array
    生成干扰线
  • 原文地址:https://www.cnblogs.com/feng9exe/p/6100072.html
Copyright © 2011-2022 走看看