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

Linux部分底层机制

POSIX

  • POSIX 是一系列由 IEEE 制定的标准,旨在定义操作系统(尤其是类 Unix 系统)应该提供的应用程序接口(API)、命令行接口和工具环境。

  • 它的核心目标是 可移植性。如果一个程序遵循 POSIX 标准编写,那么它应该能够在任何实现了该 POSIX 标准的操作系统(如 Linux, BSD, macOS, Solaris 等)上编译和运行,而无需进行重大修改。

与线程的关系

  • POSIX 线程标准(通常称为 Pthreads)是 POSIX 标准的一部分(具体在 IEEE Std 1003.1c)。

  • 它定义了一套 统一的、跨平台的 C 语言 API 用于创建、同步和管理线程。这套 API 是开发者编写多线程程序的主要接口。

  • 关键 API 示例

    • pthread_create():创建新线程。

    • pthread_join():等待线程终止并回收资源。

    • pthread_exit():终止当前线程。

    • pthread_mutex_init() / pthread_mutex_lock() / pthread_mutex_unlock():互斥锁操作。

    • pthread_cond_init() / pthread_cond_wait() / pthread_cond_signal():条件变量操作。

    • pthread_key_create() / pthread_setspecific() / pthread_getspecific():线程特定数据(TLS)管理(旧接口)。

  • 核心作用: 为开发者提供标准、可移植的多线程编程接口。开发者只需要学习 Pthreads API,就可以在多种支持 POSIX 的系统上编写多线程程序,无需深入了解底层操作系统(如 Linux)的具体实现机制(如 clone, futex)。

总结

  • POSIX (Pthreads): 定义标准接口。开发者用这些函数 (pthread_create, pthread_mutex_lock 等) 编写跨平台多线程程序。
  • 你用 POSIX 函数写多线程代码。

clone()

  • clone() 是 Linux 特有的一个底层系统调用。它是 Linux 内核创建新的执行流(无论是传统意义上的进程,还是线程)的基础机制。

  • 它非常灵活,通过传递一组标志位 (flags) 来控制新创建的“任务”(内核用 task_struct 表示)与其父任务共享哪些资源。

与线程的关系?

  • 线程的本质: 在 Linux 内核看来,线程就是一组共享了大量资源(特别是虚拟内存空间 CLONE_VM)的轻量级进程(LWP)。

  • 线程的创建: 当你在用户空间调用 pthread_create() (POSIX API) 时,底层的线程库(如 NPTL)最终会调用 clone() 系统调用来请求内核创建新线程。

  • 关键标志位 (flags) 用于线程

    • CLONE_VM: 共享虚拟内存空间(代码段、数据段、堆等)。这是线程区别于进程的核心标志。

    • CLONE_FS: 共享文件系统信息(根目录、当前工作目录等)。

    • CLONE_FILES: 共享打开的文件描述符表

    • CLONE_SIGHAND: 共享信号处理程序。

    • CLONE_SYSVSEM: 共享 System V 信号量撤销值。

    • CLONE_THREAD: 将新任务放在同一个线程组内(同一个 TGID/PID 下)。这是 NPTL 要求的关键标志。

    • CLONE_SETTLS: 设置新任务的 TLS (Thread Local Storage) 段。

    • CLONE_PARENT_SETTID / CLONE_CHILD_CLEARTID: 用于用户空间线程库高效管理线程 ID 和通知线程退出。

  • 对比进程创建 (fork()): fork() 在 Linux 上最终也是通过 clone() 实现的,但它传递的标志位不包含 CLONE_VM, CLONE_FS, CLONE_FILES 等。这导致子进程获得父进程资源的独立副本(通常通过写时复制)。

  • 核心作用: 提供 Linux 内核创建线程或进程的底层机制。它定义了新执行流与父执行流之间资源共享的粒度pthread_create() 是对 clone() 用于创建线程场景的高层封装。

简单来说

  • clone(): Linux 内核创建线程的底层机制。pthread_create() 最终调用 clone() 并设置特定的资源共享标志 (CLONE_VM, CLONE_FILES 等) 来创建内核线程(LWP)。
  • 创建线程时,POSIX 库用 clone() 告诉内核怎么建新线程(共享哪些资源)。

NPTL

了解NPTL是现代 Linux 发行版默认使用的 Pthreads 实现。

优势:

  • 1:1 模型: 严格的一个用户线程对应一个内核调度实体(LWP / task_struct)。这使得调度高效且符合 POSIX 语义。

  • 高效同步: 利用内核提供的 futex (Fast Userspace muTEX) 机制实现高效的互斥锁、条件变量等同步原语。futex 结合了用户空间的快速路径(无竞争时)和内核空间的慢速路径(需要阻塞时),极大地减少了系统调用的开销。

  • 健壮的信号处理: 正确实现了 POSIX 信号语义。

  • 线程组管理: 内核支持线程组 (TGID),所有线程共享同一个 PID。

  • /proc 文件系统支持: /proc/[pid]/task 目录列出了进程中的所有线程(LWP),每个线程有自己的子目录(以其 TID 命名)。

  • 更好的性能和可伸缩性: 能够高效支持大量并发线程。

理解TLS变量

  • TLS 是一种存储类(Storage Class)。

  • 它允许你定义全局或静态变量,但每个线程都拥有该变量的独立副本

  • 一个线程对自身 TLS 变量的读写操作不会影响其他线程中同名的 TLS 变量。

  • 允许每个线程拥有一个变量的独立副本。一个线程修改其 TLS 变量不会影响其他线程的同名变量。

为什么需要?

  • 线程私有状态: 在多线程环境中,有些数据是线程特定的,而不是所有线程共享的全局状态。例如:

    • errno:每个线程需要有自己独立的错误码副本。

    • 用户身份或会话信息(在 Web 服务器中)。

    • 数据库连接句柄(每个线程管理自己的连接)。

    • 复杂的函数调用链中避免传递大量上下文参数。

    • 需要线程安全的伪随机数生成器种子。

  • 避免锁竞争: 如果使用全局变量加锁来模拟线程私有数据,会带来不必要的锁竞争开销。TLS 天然避免了这种竞争。

与线程的关系?

  • 线程创建与销毁: 当一个线程被创建时,系统会为它分配一块私有的 TLS 内存区域,用于存储其所有 TLS 变量的初始值或零初始化值。当线程终止时,这块内存(包括其中 TLS 变量的值)会被自动回收。

  • 访问机制: 编译器/链接器会为 TLS 变量分配在特殊的段(.tdata 用于初始化的 TLS,.tbss 用于未初始化的 TLS)。运行时,操作系统和线程库协作,使得每个线程能通过特定的段寄存器(如 FSGS 寄存器)加上该变量在 TLS 块中的偏移量来访问自己的 TLS 变量副本。这个过程对开发者是透明的,像访问普通变量一样使用即可。

  • 核心作用: 提供一种高效、安全、易用的机制来存储和管理线程私有的全局数据,是编写清晰、高效、线程安全代码的重要工具。

简单来说

  • TLS 变量: 提供线程私有存储的语言/编译器级机制。用于存储线程特有的状态(如 errno, 会话数据),避免使用全局变量+锁带来的开销和复杂性。
  • 你想让每个线程有自己的“全局”变量?用 TLS (__thread / thread_local) 就行。

在这里插入图片描述

http://www.xdnf.cn/news/1381303.html

相关文章:

  • LeetCode-279. 完全平方数
  • Linux 软件编程(十三)网络编程:TCP 并发服务器模型与 IO 多路复用机制、原理epoll
  • 工业机器人如何通过Modbus TCP转CanOpen网关高效通信!
  • HTML贪吃蛇游戏实现
  • RAW API 的 TCP 总结2
  • 鸿蒙Harmony-从零开始构建类似于安卓GreenDao的ORM数据库(四)
  • 刷题日记0828
  • 未来模型会转向多模态吗
  • Logstash数据迁移之mysql-to-kafka.conf详细配置
  • 领悟8种常见的设计模式
  • 导入文件允许合并表格
  • HBase Compaction HFile 可见性和并发安全性分析
  • audioMAE模型代码分析
  • 流程控制语句(3)
  • 帕萨特盘式制动器cad+设计说明书
  • 【C语言16天强化训练】从基础入门到进阶:Day 13
  • week5-[一维数组]归并
  • 公共字段自动填充
  • 云计算学习100天-第29天
  • 基于SamOut的音频Token序列生成模型训练指南
  • Linux shell getopts 解析命令行参数
  • 算力沸腾时代,如何保持“冷静”?国鑫液冷SY4108G-G4解锁AI服务器的“绿色空调”!
  • 使用Rag 命中用户feedback提升triage agent 准确率
  • Elasticsearch数据迁移方案深度对比:三种方法的优劣分析
  • linu 网络 :TCP粘包及UDP
  • 【C++】C++11的右值引用和移动语义
  • STAGEWISE实战指南:从集成到使用的完整解决方案
  • vscode pyqt5设置
  • 【ai编辑器】使用cursor-vip获得cursor的pro版 pro plan(mac)
  • uniapp vue3 canvas实现手写签名