Linux Kernel 内核同步之原子操作
Linux Kernel 内核同步之原子操作 原子操作是指指令以原子的方式执行,执行过程不会被打断。要保证操作的原子性和完整性,需要“原子地”(不间断地)完整 读-修改-回写(RMW) 机制。 static int i = 0; void thread_A_func() { i++; } void thread_B_func() { i++; } 上面代码的理想执行结果是i 为 2,但事实并非如此, i 有一定的概率为 1。对于 thread_A 和 thread_B 进行的操作可以简单理解为:读 - 修改 - 回写。从单处理器和多处理器角度分析: 单核处理器:thread_A 与 thread_B 存在并发,当 thread_A 执行完 读 操作,CPU 有可能切换为 thread_B 执行 读 操作,这样最终的结果为 1. 多核处理器:thread_A 与 thread_B 存在并行,thread_A 与 thread_B 可能同时执行 读 时,存储仲裁器判定其中一个 CPU 先读,另一后读,然后分别+1,这样最终结果也为 1. 因此,要想保证结果的正确性,我们必须保证上面的操作完整地原子地(不间断地)完成 读-修改-回写。 一、Linux 内核提供原子操作 API Linux 内核提供了两组原子操作 API 函数,一组是对整形变量进行操作的,一组是对位进行操作的,我们接下来看一下这些 API 函数。
Linux - 内存管理 - 分页虚拟存储理论
分页虚拟存储理论 0x00 很久之前 在很久之前,计算机使用单程序存储管理。 在这种管理模式下,每次只能运行一个程序。操作系统每次将相应的程序从磁盘加载到 RAM 中。直至进程运行结束后跳转到操作系统代码,操作系统再根据用户需求将程序装入 RAM 中,覆盖掉旧的程序。存在问题: 一次只能运行一个程序 进程(程序)的切换很慢 程序的大小取决于 RAM 物理内存的大小 事实上,后面又发展了多道程序,交换技术等技术来试图解决上述问题但效果不好,这里就不展开讲了,但为什么会讲一下单道存储管理,因为其与 Linux 虚拟存储空间布局很像,暂时无需知道什么是虚拟存储空间。 0x01 虚拟存储器 Virtual Memory 虚拟存储技术发展的根本原因: RAM 小且昂贵,无论是上世纪还是当下,RAM 都是小且昂贵的资源,所以我们不得不充分利用,进而发展出虚拟存储技术。假设我们的 RAM 可以无限大且廉价。 虚拟存储的基础及事实: 局部性原理:程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分。这也意味着并不需要完全把程序加载到 RAM 也能保证程序的执行。 磁盘空间很大且足够便宜,可以把程序暂时不需要的那一部分放在磁盘上,把需要的那部分放在 RAM 上。 Virtual Memroy[1] 由 Fotheringham 在 1961 年提出[2],其基本思想是: 程序的代码数据和栈的总大小可以超过物理内存(RAM) 操作系统将正在运行的程序的需要的那部分保留在内存中,而将当前不使用的部分放置在磁盘上,根据需要调入内存。 根据虚拟存储器实现的技术可以分为: 页式:采用 分页 Paging 技术 段式:采用 分段 Segmentation 技术 分页分段结合:Paged Segmentation 目前大多数虚拟存储管理系统都采用分页 paging 技术,本文也仅讲解分页存储管理。
Valgrind 基础介绍与框架概览
Valgrind 基础介绍与框架概览 Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具,本文简单分析 Valgrind 基本原理及其框架组成,并记录其在嵌入式设备上的移植与调试过程。 一、插桩技术概述 插桩(instrumentation)技术是指在程序源码或二进制代码中插入监测代码实现对程序的监视。达到记录函数进入和退出、监控内存读写、统计执行时间、跟踪异常等。 插桩在实现上可分为两类: 静态插桩 Static Instrumentation:在程序编译之前或编译期间插入代码,即在源代码或中间代码中插入检测代码,最终编译成带有插桩的可执行文件。 动态插桩 Dynamic Binary Instrumentation DBI:在程序运行中进行插桩,其操作对象为机器码。动态二进制插桩工具主要包含 Pin,Valgrind,DynamoRIO 等。 二、Valgrind Framework Valgrind 本质上是一套核心框架 framework,其提供了核心 Core 及 APIs ,在此框架基础上开发出 7 个工具: 工具 描述 Memcheck 内存错误检测,用于检测内存泄漏、越界访问、使用未初始化内存等内存相关错误 Helgrind 线程错误检测,检测数据竞争(race conditions)和死锁 DRD 线程错误检测,使用与 Helgrind 不同技术 Cachegrind 缓存和分支预测分析 Callgrind 基于 Cachegrind,但额外生成调用图,分析函数调用及其性能影响 Massif 堆内存使用分析工具,帮助找出内存使用高峰及其来源 DHAT 分析堆内存分配和释放的详细情况 三、嵌入式平台调试 memory leak 指定 toolchains export GCC_PATH=/your_path_for_linaro/bin export CC=${GCC_PATH}/aarch64-linux-gnu-gcc export LD=${GCC_PATH}/aarch64-linux-gnu-ld export AR=${GCC_PATH}/aarch64-linux-gnu-ar 编译配置 cd valgrind ./autogen.sh ./configure --prefix=`pwd`/Inst --host=aarch64-unknown-linux --enable-only64bit 编译安装 make -j4 install 准备带有 debug info 的 ld.so valgrind memcheck 需要使用带调试信息的 ld.so, 其会拦截并替换 ld.so 中的某些符号(比如 strlen)以实现正确的检测[1]。 否则会报 cannot be set up 错误,ld.so 可以在交叉编译工具链中找到。