程序员自我修养读后记

一.基础知识

1.cpu的速度非常高,但是外设的速度比较低,通过总线来进行传输,由于速率之间不匹配因此有了南桥、北桥,北桥连接一些高速外设比如内存,南桥连接一些低频外设打印机、键盘等等,而cpu已倍频的方式运行。
2.在操作系统中多任务需要对进程进行内存隔离,因此有了增加了中间层虚拟内存,最开始使用的是分段的方式,一整段进行映射虽然做了隔离但是利用率较低,因此采用了更小的粒度,从而有了分页机制。每个进程有自己的页表,通过mmu将虚拟地址映射到物理地址,当访问到的页不在物理内存中时就发生了缺页异常。
3.在多线程中,需要对共享资源进行保护,可以使用原子操作或者加锁进行同步。
4.一个可重入的函数必定是线程安全的,一个线程安全的函数可能是加锁进行了保护。可重入函数需要保证不使用非const的全局变量,不使用static的局部变量,仅依赖于调用方传入的参数。
5.volatile可以防止编译器对指令进行重排,变量不从寄存器中读取改为直接读取内存。虽然阻止了编译器对指令进行重排,但是这没有什么意义,因为cpu的流水线也是乱序发射的。
6.可以通过barrie(屏障)的方式,barrie之下的指令一定在barrie之上的指令执行完后再执行。可以到singleton中常见的double-check,其实也是不安全的,这是因为new这个操作符不是一个原子的操作,可能先返回分配的内存地址再调用构造函数,这时候检查地址不为空则获取到的是一个未初始化的对象指针。可以在new之后加入barrier()。

// A code block
Singleton* Singleton::getInstance()
{
    if(NULL == instance)
    {
    //对象实例第一次被创建后, 没有线程会进入该区域了, 因此该版本的性能与版本一几乎相同,且安全性与版本二一样好
    lock(mutex);
    if(NULL == instance) //检查对象是否已经存在
    {
        //对象构造区域
        instance = new Singleton();
        barrier();
    }
    unlock(mutex);
    }
    return instance;
}

二.编译链接

1.gcc hello.c的过程是非常复杂的,这个gcc其实是包含了多种工具(预编译编译程序cc1、汇编器as、连接器ld)的一个集合,其中包括了:
a.预处理(将c代码中#inlclude指令展开、#define展开、#pragma编译器指令、删除注释等),可以使用gcc -E hello.c -o hello.i生成hello.i文件
b.编译(词法分析、语法分析、语义分析等,将c代码的单个文件编译为汇编文件) gcc -S hello.i -o hello.s
c.汇编器 as hello.s -o hello.o(同gcc -c hello.s -o hello.o),将汇编文件转换为二进制
d.链接器 将多个目标文件、库打包成一个可执行文件。
现代的开发中经常涉及到跨文件的函数调用、变量使用,在编译的过程中时分文件进行编译的此时并不知道这些函数、变量的绝对地址,只是记录一个符号,称作符号未决。而链接的过程就是确定这些符号的最终地址、空间分配、符号决议和重定位(古老的程序中,地址是写死的,每当程序修改就得修改变量地址被叫做重定位)。

三.目标文件格式

1.目标文件采用elf格式存储,分成多个段,可以使用readelf -s xxx.out的方式查看各个段。
在这里插入图片描述
.text 代码段
.data 数据段 存放初始化的全局变量、局部静态变量等
.rodata 只读数据段 存放字符串常量、全局const变量等
.symtab 符号表
.init段保存了进程的初始化代码,main函数之前的工作,linux进程的入口一般为_start,这个函数是glic的一部分。
2.c++允许函数重载是在编译器上做的支持,符号表中对函数进行修饰加上函数的参数进行符号修饰来表示不同的函数

四.静态链接

1.合并多个目标文件中的段
2.符号解析并进行重定位,重定位表中记录着需要被重定位的数据、符号

六.可执行文件的装载与进程地址空间

1.进程创建过程
创建一个独立的虚拟地址空间
读取elf文件,建立虚拟地址空间和elf文件的映射关系,进程的虚拟地址空间由多个vma(匿名虚拟内存区域)组成,对应内核中task_struct—>mm_struct–>vm_area_struct(匿名虚拟内存区域形成一个双向链表)
将cpu的指令寄存器设置为elf的入口地址,启动运行
在这里插入图片描述

七.动态链接

1.为什么使用动态链接
多个可执行文件引用同一个静态库,造成空间浪费
更新、部署、发布新版本库的时候会造成维护非常麻烦
2.动态链接是由动态链接器完成,而不是ld工具,是把链接这个过程推迟到运行时进行,在elf文件中存放了GOT(全局偏移表,里面存放了未决符号的地址指针数组,当装载动态库的时候才填入地址,即在装载前引用这些未决地址的话是使用了GOT中的指针)

八.其他

1.eip寄存器 是存储下一个指令的寄存器
2.esp是栈指针寄存器
3.ebp 基址指针寄存器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值