_dl_runtime_resolve如何实现多线程安全性?
_dl_runtime_resolve的多线程安全性实现机制
当多个线程同时调用同一个尚未完成GOT解析的函数时,_dl_runtime_resolve主要通过以下核心机制保证线程安全:
原子检查+双重校验:首先通过原子操作读取GOT表中的目标项,判断是否已经完成解析。如果发现还处于未解析的占位状态,才会进入后续的锁逻辑;拿到锁之后会再次检查GOT项——这一步是为了防止等待锁的过程中,已经有其他线程完成了解析工作,避免重复执行解析流程。
全局锁保护临界区:进入解析流程的线程会获取全局加载锁(比如glibc中的
_dl_load_lock),确保同一时间只有一个线程执行实际的符号解析与GOT更新操作。其他线程会在锁上阻塞等待,直到解析完成锁被释放。原子写入GOT表:当符号解析完成、得到函数的真实地址后,会用原子指令将地址写入GOT表。这种原子写入能保证所有线程看到的GOT项要么是未解析的占位值,要么是完整的有效地址,不会出现半更新的中间状态,避免线程读到错误的部分地址。
线程本地存储(TLS)辅助防重入:部分实现会利用TLS标记当前线程正在解析的符号,避免同一线程因递归调用触发重复解析,同时也能辅助锁的逻辑判断,减少不必要的锁竞争。
举个glibc实现里的简化逻辑:
// 原子读取GOT项,判断是否未解析 if (__atomic_load_n(got_entry, __ATOMIC_ACQUIRE) == placeholder) { __libc_lock_lock(&_dl_load_lock); // 再次检查,防止等待期间已被其他线程解析 if (__atomic_load_n(got_entry, __ATOMIC_ACQUIRE) == placeholder) { // 执行实际的符号解析 resolved_addr = _dl_fixup(...); // 原子写入GOT表 __atomic_store_n(got_entry, resolved_addr, __ATOMIC_RELEASE); } __libc_lock_unlock(&_dl_load_lock); }
内容的提问来源于stack exchange,提问作者daisy
相关产品推荐
相关产品推荐

