程序员的自我修养-链接、装载与库读书笔记

程序员的自我修养-链接、装载与库读书笔记


目录
第一章 温故而知新
第二章 目标文件里有什么


温故而知新

  1. 为什么系统内存分段、分页?
    直接将物理内存分配给进程使用存在三个问题:

    * 地址空间不隔离 所有程序都直接访问物理地址,程序所使用的内存空间不是相互隔离的,恶意程序会撰改其他程序的内存数据达到破坏的目的  
    * 内存使用效率低  
    * 程序运行的地址不确定  
    

    解决上面存在的问题采用了一种间接访问地址的方法:虚拟地址

    分段:把一段程序所需要的内存空间大小的虚拟空间映射到某个地址空间。这样可以达到程序与地址空间隔离不会访问别的程序的内存。

    同时也解决程序运行地址不确定问题但是这样子会有一个问题,当内存不够用时被换入换出到磁盘的都是整个程序势必会降低效率。
    所以我们需要进行粒度更小的换入换出。
    

    分页:分页就是解决分段的大粒度问题。把地址空间认为的等分成固定大小的页,每一页的大小有硬件决定,或者硬件支持多种大小

    的页,由操作系统选择决定页的大小。但同一时刻只能选择一种大小,所以对与整个操作系统来说页就是固定的。
    
  2. 什么是线程?

    线程 有时被称为轻量级进程,是程序执行的最小单元。一个标准的线程有线程ID、当前指令指针(PC)、寄存器集合、堆栈组成。

    同一个进程的所有线程之间共享程序的内存空间(包括代码段、数据段、堆等)及一些进程级的字段(如打开的文件、信号)。  
    线程页拥有自己的私有存储空间  
       *  栈,一般情况下认为私有的数据  
       *  线程局部存储  (TLS)  
       *  寄存器(包括PC)  
    

    |线程私有|线程之间共享|
    |——-|———|
    |局部变量|全局变量|
    |函数参数|堆上的数据|
    |TLS |函数里的静态变量|
    | |程序代码任何线程都有权利读取并执行任何代码|
    | |打开的文件,A线程打开的文件可以由B线程读写|

  3. 同步与锁

    |类型|说明|适用场合|
    |—|—-|——|
    |二元信号量|最简单的锁,只有两种状态:占用与非占用;|适合被唯一一个线程独占访问的地资源|
    |多元信号量|简称信号量(semaphore)|允许有多个线程访问|
    |互斥量(Mutex)|与二次元类似,但是信号量可以被系统中的一个线程获取之后由另外一个线程释放;而互斥量,要求谁获取就是负责释放|资源近同时允许一个线程访问|
    |临界区(critical section)|比互斥量更为严格的同步手段;一个进程创建了一个互斥量或者信号量,另一个进程试图区获取该锁是合法的|仅限于本进程,其他进程无法获取该锁|
    |读写锁(read-write lock)|有两种获取方式:共享、独占||
    |条件变量(condition variable)|一个条件变量可以被多个线程等待;线程可以唤醒条件变量,此时所有等待条件变量的线程都会被唤醒||

目标文件里有什么

  1. 目标文件
    程序编译完成之后主要分为两种段:程序指令和程序数据

    1. 一般而言c编译的可行语句都编译成机器代码保存在.text段 (程序指令
    2. 已初始化的全局变量和局部静态变量都保存在.data段(虽然位初始化的全局变量、局部静态变量默认值都是0,没必要放在这里浪费内存)(程序数据
    3. 未初始化的全局变量和局部静态变量一般存放在.bss段(只是未这些变量预留位置而已,所以在文件中不占据空间(程序数据
    4. C/C++中,编译器默认为函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。

      1
      __attribute__((week))
      1
      2
      3
      4
      5
      6
      7
      8
      extern int ext;
      int weak;
      int strong=1;
      __attribute__((weak)) weak2=2;
      int main()
      {
      return 0;
      }
坚持原创技术分享,您的支持奖鼓励我继续创作!