当前位置: 首页 > news >正文

附录:glibc-2.4 pthread 源码简要(了解)

目录

一、线程创建核心流程分析

1、入口函数:__pthread_create_2_1

2、核心数据结构

3、关键函数实现

二、线程创建的核心机制总结

三、关键问题与解决方案

四、代码注释与补充说明


一、线程创建核心流程分析

1、入口函数:__pthread_create_2_1

路径nptl/pthread_create.c

函数签名

int __pthread_create_2_1(pthread_t *newthread, const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg
);

关键代码解析:

线程属性处理

const struct pthread_attr *iattr = (struct pthread_attr *)attr;
if (iattr == NULL)iattr = &default_attr; // 使用默认属性
  • 若用户未指定属性,使用全局默认属性default_attr

线程控制块(TCB)分配

struct pthread *pd = NULL;
int err = ALLOCATE_STACK(iattr, &pd); // 分配栈空间并初始化TCB

通过宏ALLOCATE_STACK调用allocate_stack函数,完成以下操作:

  • 申请内存(优先从缓存获取,失败则调用mmap)。

  • 初始化线程描述符(TCB)结构体struct pthread

  • 设置栈保护区域(guardsize)。

TCB关键字段初始化

pd->start_routine = start_routine; // 用户线程函数
pd->arg = arg;                     // 用户参数
pd->flags = ...;                   // 继承父线程调度属性
pd->joinid = (iattr->flags & ATTR_FLAG_DETACHSTATE) ? pd : NULL; // 分离状态标记

调度参数配置

if (attr != NULL && (iattr->flags & ATTR_FLAG_NOTINHERITSCHED)) {// 显式设置用户指定的调度策略和优先级pd->schedpolicy = iattr->schedpolicy;memcpy(&pd->schedparam, &iattr->schedparam, sizeof(struct sched_param));
}

线程创建与启动

err = create_thread(pd, iattr, STACK_VARIABLES_ARGS);
*newthread = (pthread_t)pd; // 返回TCB地址作为线程ID

2、核心数据结构

线程属性结构体 (struct pthread_attr)

struct pthread_attr {struct sched_param schedparam; // 调度参数int schedpolicy;               // 调度策略(SCHED_OTHER/FIFO/RR)int flags;                     // 属性标志位(如分离状态)size_t guardsize;              // 栈保护区域大小void *stackaddr;               // 用户指定栈地址(可选)size_t stacksize;              // 栈大小cpu_set_t *cpuset;             // CPU亲和性设置
};

线程控制块 (struct pthread)

struct pthread {union {tcbhead_t header;          // TCB头部(含TLS信息)void *__padding[16];       // 保留字段};list_t list;                   // 栈缓存链表节点pid_t tid;                     // 线程IDpid_t pid;                     // 进程IDvoid *(*start_routine)(void *);// 用户线程函数void *arg;                     // 用户参数void *result;                  // 线程返回值(供pthread_join使用)int cancelhandling;            // 取消状态标志位struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE]; // TLS数据// ... 其他字段(锁、事件、栈信息等)
};

3、关键函数实现

1. allocate_stack: 栈与TCB分配

路径nptl/allocatestack.c

逻辑流程

计算栈大小

size = attr->stacksize ?: __default_stacksize;
size &= ~__static_tls_align_m1; // 对齐调整

内存分配策略

  • 优先从缓存获取:调用get_cached_stack

  • 失败后动态分配

    mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  • TCB位置计算

    pd = (struct pthread *)((char *)mem + size - TLS_TCB_SIZE) - 1;

保护区域设置

if (mprotect(guard, guardsize, PROT_NONE) != 0) {// 处理保护区域创建失败
}

2. create_thread: 线程启动

核心操作

设置clone标志

int clone_flags = CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGNAL|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID;

调用do_clone

int res = do_clone(pd, attr, clone_flags, start_thread, STACK_VARIABLES_ARGS, stopped);
  • do_clone内部通过汇编宏ARCH_CLONE调用系统调用clone

异常处理:若线程创建失败,释放资源:

__deallocate_stack(pd);

3. do_clone: 系统调用封装

汇编实现(x86_64示例):

ENTRY(__clone)/* 参数校验与栈调整 */movq %rcx, 8(%rsi)    # 保存用户参数movq %rdi, 0(%rsi)    # 保存线程函数地址/* 执行clone系统调用 */movl $SYS_ify(clone), %eaxsyscalltestq %rax, %raxjl SYSCALL_ERROR_LABELjz L(thread_start)    # 子线程入口

二、线程创建的核心机制总结

  1. 内存管理

    • TCB与栈空间连续分配,TCB位于栈顶或栈底(依赖架构)。

    • 默认栈大小通过__default_stacksize定义(通常为2MB)。

  2. 系统调用集成

    • 通过clone创建轻量级进程,共享地址空间但独立调度。

    • 使用CLONE_SETTLS设置线程本地存储(TLS)。

  3. 扩展性设计:用户态调度器可行性:通过拦截pthread_create和自定义队列,可在用户态实现调度策略(如协程库)。


三、关键问题与解决方案

  1. NUMA架构优化

    • 问题:默认属性可能导致远端内存访问。

    • 建议:显式设置stackaddr或使用mbind绑定内存节点。

  2. 栈溢出防护:通过guardsize创建不可访问的保护页,触发SIGSEGV

  3. 资源泄漏防护:分离线程(detached)自动释放TCB,非分离线程需通过pthread_join回收。


四、代码注释与补充说明

  1. ALLOCATE_STACK宏展开:参数stackaddrstacksize用于回传栈信息。

    #define ALLOCATE_STACK(attr, pd) \allocate_stack(attr, pd, &stackaddr, &stacksize)
  2. TLS布局控制

    • TLS_TCB_AT_TP:TCB位于线程指针(TP)地址。

    • TLS_DTV_AT_TP:动态线程向量(DTV)位于TP地址。

  3. 性能优化细节:栈着色(Stack Coloring):通过COLORING_INCREMENT避免多线程栈地址冲突。

        通过以上分析可见,glibc的pthread实现通过分层设计(用户API→运行时库→系统调用)实现了高效的线程管理,同时保留了足够的扩展接口供用户态调度器实现。

http://www.dtcms.com/a/545972.html

相关文章:

  • 网站注册费用济南网站优化哪里做的好
  • 晋中住房与城乡建设厅网站湖南手机版建站系统哪家好
  • 记类成员变量 vs 方法中的变量
  • 企业网站模板建站建网站浩森宇特
  • 项目(四)
  • 徐州 商城网站设计wordpress变为中文
  • Rust Feature Flags:编译期配置的艺术与工程实践
  • 贵金属网站建设阿里云域名备案查询
  • Java后台面试 常见问题
  • 如何自己建站网站制作深圳公司网站推广
  • 【RAG架构】RAG架构概要
  • 6.5 大数据方法论与实践指南-安全合规-账号体系
  • Vue 系列之:Vue2 双端 Diff 算法原理
  • 网站建设与维护案列领优惠券的网站怎么做
  • 【AIGC面试面经第四期】LLM-Qwen相关问答
  • 百度首页网站的设计用php做企业网站的可行性
  • 前端流水线连接npm私有仓库
  • 创可贴设计网站官网怎么建公司网站
  • leetcode375.猜数字大小II
  • 江西网站开发方案建设一个门户网站 费用
  • Android设备使用AirPods
  • 用js做的网站页面教育机构有哪些
  • @Transactional 事务注解坑之为什么自调用(同一个类中方法互相调用)事务不生效?
  • 使用 WSL 在 Windows 上安装 Linux
  • 有专业做网站的学校吗网站seo是啥
  • Agent记忆框架(三)
  • 建歌网站多少钱在百度备案网站
  • F040 python中医药图谱问答|双推荐算法+知识图谱+智能问答+vue+flask+neo4j前后端分离B/S架构|爬虫|图谱生成|全套
  • 南京做网站企业如何建网站做推广
  • 网页设计素材螺蛳粉图seo 网站两个ip