C++ 中以继承的方式实现动态多态是存在额外开销的, 具体地说,C++ 对象使用了额外的内存保存关于基类信息才实现了运行时多态. 但这种额外信息究竟以何种方式在对象的内存中报错对我来说仍是未知. 受到前人文章的启发, 本文借助 GDB 调试器一步步地观察记录 C++ 对象的内存布局, 力求理解实际 C++ 编译器 (gcc 9.4.0) 对 C++ 对象的内存布局以及派生类的实现.

阅读全文 »

Memory Barrier 是 CPU 提供的一种机制, 它的作用是在程序中设置一个内存屏障, CPU 会保证所有在 Memory Barrier 之前的代码对内存的访问 (改动) 在 Memory Barrier 之后都是可见的. 这一保证据有两方面的效应:

  1. 所有 Memory Barrier 之后的代码都不能被重排 (Reordering) 到 Memory Barrier 之前执行
  2. 当执行到 Memory Barrier 时, CPU 必须在所有 Core 之间同步 Cache, 保证此刻所有 Core 看到的内存是一致的.

Memory Order 是 C++ 11 提供的一种并发编程机制, 它允许显式地限制编译器/CPU 对指令的重排 (Reordering), 以及显式地控制多核 CPU Cache 之间的同步. 其效果是使得不同线程/不同 CPU Core 所观察到的原子操作附近的内存操作具有可预测的顺序.

阅读全文 »

对于被广泛使用的标准库或其他库, 如果一个系统中多个程序都在引用相同的符号, 此时使用静态库将需要为每个程序都加载一份符号定义的代码和数据, 这对内存是极大的浪费.

共享库 (shared library) 是解决静态库这一问题的产物. 共享库是一个目标模块, 在运行或加载时可以被加载到任意内存地址, 并和一个在内存中的程序链接起来. 这一过程称为动态链接, 是由一个叫做 动态链接器 (dynamic linker) 的程序执行的.

阅读全文 »

链接器 链接 的结果是生成一个可执行目标文件, 这个目标文件中包含将程序加载到内存并运行的所有信息. 下图是一个 ELF 可执行目标文件所包含的信息:

阅读全文 »

现代 x86-64 系统使用可执行可链接格式文件 (Executable and Linkable Format, ELF)

ELF 文件的结构:

阅读全文 »

程序从源代码到可执行文件需要经过 4 个步骤, 链接就是其中重要的一步.

链接器的主要工作是将具备引用关系的不同编译单元的编译结果 (i.e. 可重定位目标文件) 相互连接, 组成一个可执行文件.

静态链接器以一组可重定位目标文件和命令行参数作为输入, 生成一个完全链接的, 可以加载运行的可执行目标文件.

阅读全文 »

计算机存储器具有金字塔式结构, 即: 较高层的存储器容量小速度快, 低层的存储器容量大速度慢, 计算机通过缓存的方式提高储存系统的整体性能.

阅读全文 »

The core functionality of an OS

操作系统的核心任务在于同时支持多个活动,即,操作系统必须将硬件资源分时共享给所有的进程使用。

为了保证进程的活动质量,操作系统还必须保证进程的执行是 独立/孤立(isolation) 的,即进程不会因意外或恶意目的破坏其他进程的执行,以及不会被其他进程破坏。

保证独立性的前提下,进程之间合理的交互和通信也应该被支持,因此操作系统应该提供 进程间通信 的方式,例如 pipe

总的来说,操作系统必须为进程提供以下服务:

  • 时分复用 底层硬件
  • 独立 的执行环境(内存,内核状态等)
  • 进程之间的合法 交互
阅读全文 »
0%