• 程序员的自我修养 学习笔记(4)


            可执行文件只有装载到内存以后才能被CPU执行。程序就将是菜谱,CPU就像是厨师,计算机的其他硬件就像是厨具,整个炒菜的过程就是一个进程。同样的一份菜谱,不同人可以做出来不同的味道。这个类比真是巧妙。

        Linux下面,进程最大使用3G的虚拟空间

        Windows下面,进程最大使用2G的虚拟空间

    现在计算机,配置超过4G的内存的电脑已经不是不可能了,在这种情况下,32位CPU能够访问到大于4G的空间吗?如果此空间指的是虚拟地址空间,由于32位CPU的指针只能是32位,最大寻址范围是0~4GB。如果此空间指的是实际内存空间,Intel的Pentium Pro CPU采用36位物理地址,可以访问高达64G的物理内存,这种机制叫做PAE(Physical Address Extension)。

        覆盖装入(Overlay):程序员必须手工将程序分割成若干块,然后编写一个小的辅助代码来管理这些模块何时应该驻留内存、何时应该被替换掉。

        页映射(Paging):是虚拟存储机制的一部分。

    创建一个进程:

    1. 创建一个独立的虚拟地址空间

    2. 读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系

    3. 将CPU的指令寄存器设置成可执行文件的入口地址,启动运行

    静态链接存在空间浪费和更新困难两个因素。

    1. 如果每个程序都静态链接,那么在多个程序执行时,就会存在很多冗余的副本

    2 如果静态链接库中有某一个模块更新了,那么所有基于此库的程序都要重新编译、下载更新一次,对用户来说非常不方便。

    解决这个问题的方法,是动态链接。要做到动态链接,就要把程序的模块相互分割开来,形成相互之间较独立的文件,而不再将它们静态地链接在一起,简单的讲,在程序编译时,不进行链接,在实际运行时,才进行链接。

           共享对象在编译时,不能假设自己在进程虚拟地址空间中的位置,可执行文件基本可以确定自己在进程虚拟空间地址中的起始位置,因为可执行文件往往是第一个被加载的文件,它可以选择一个固定空闲的地址,比如Linux下,一般是0x8040_0000,WIndows下面一般是0x0040_0000

        malloc申请的内存位于堆空间内。malloc是怎么实现的呢?从简单的思路来想,把进程的内存管理全部交给操作系统内核来处理,操作系统提供系统调用,供程序申请堆内存使用。简单是简单,考虑到堆申请操作比较频繁,系统调用开销较大,效率不高,因此,需要改进。怎么改进呢?

          书中给出了一个很好的类比,程序向操作系统”批发”一块较大的堆空间,由运行库来管理“批发来的”堆空间,对于同一个商品,只能暂时借给一个客人,存放商品的货柜是一一对应的,哪儿借出的商品,归还时,就还到哪里去(从1号仓库中借出的商品,归还时要还到1号仓库中去),一个借出对应一个归还,不能乱套,不能有借无换。

         Linux下的堆管理,系统提供了两个系统调用接口,brk和mmap。

    brk的原型为: int brk(void* end_data_segment)

           实际作用是设置进程数据段的结束地址(可以扩大和缩小数据段),增大结束地址,增大的那部分空间就可以被我们作为堆空间来使用。

    mmap,向操作系统申请一段虚拟地址空间,这段空间可以映射到某个文件,此时,称为文件映射。如果映射到其他地方,则称为匿名空间,可以作为堆使用。

    mmap原型:void *mmap(

    void* start,                     //申请空间的起始地址(设为0,则自动选择)

    size_t length,                 //申请空间的长度

    int prot..                       //申请空间的权限

    int flags,                      //映射类型(文件映射、匿名空间等)

    int fd,                          //用于文件映射的指定文件描述符和文件偏移

    off_t offset);

    Windows的进程,将地址空间分配给了各种EXE、DLL文件、堆、栈。每个线程的栈都是独立的,一个进程中有多少个线程,就应该有多少个对应的栈。对于WIndows来说,每个线程默认的栈大小是1MB。

    堆管理算法:空闲链表、位图分配,对象池(假设每次请求的都是一个固定的大小)。在很多现实应用行,堆分配算法往往是采取多种算法复合而成的。比如,对于glibc来说,小于64个字节的空间,采用的类似于对象池的方法,对大于512字节的空间申请,采用的最佳适配算法,对于大于64个字节而小于512个字节的,它会根据情况采取最佳折中策略。对于大于128K的申请,会使用mmap机制向操作系统来申请。

  • 相关阅读:
    20145222GDB调试汇编堆栈过程分析
    实验二-固件设计 20145213祁玮 20145222黄亚奇
    VS2015下如何用编译、调试程序。
    20145222《信息安全系统设计基础》第11周学习总结
    第八章教材内容总结:异常控制流
    20145222《信息安全系统设计基础》第十周学习总结
    who命令的总结
    20145222《信息安全系统设计基础》第九周学习总结
    《信息安全系统设计基础》实验过程中遇到的问题以及解决方案
    Selenium学习笔记||十四、浏览器页面刷新、前进、后退
  • 原文地址:https://www.cnblogs.com/cherishui/p/3784702.html
Copyright © 2020-2023  润新知