【Linux —— 理解pthread库和底层逻辑】

news2024/11/24 20:34:01

Linux —— 理解pthread库和pthread_t

  • 理解pthread库
    • pthread库是一个动态库
    • 底层逻辑
  • LWP
  • pthread_t
    • pthread_t的概念
    • pthread_t 的实现
    • pthread_t 与 LWP 的关系
  • 独立的栈空间
  • 管理

理解pthread库

pthread库是一个动态库

使用下面指令可以查找的系统目录下的库信息

ls /lib/x86_64-linux-gnu/libpthread.so.0 -l

在这里插入图片描述
可以看到,libpthread.so.0是一个动态库,而动态库是在运行时由程序加载。

pthread 库实现了POSIX标准下的线程管理功能,它提供了**创建、管理、同步和销毁线程的函数。**这些函数允许程序在一个进程中同时执行多个任务,即多线程操作。 这些函数都是对系统调用的封装,提供高效、标准化的多线程编程接口,它通过动态加载和链接机制,不仅节省了系统资源,还提供了灵活的升级路径。在使用pthread库时,程序可以享受标准线程操作接口的便利,而不必关心底层复杂的线程管理和调度细节。

底层逻辑

1.线程创建的目标
pthread_create的主要任务就是在一个进程中创建一个新的线程,新的线程共享地址空间和部分资源。

2.使用clone() 系统调用
在Linux中,线程的创建的核心就是使用clone()clone()fork()相似,但是比后者更加的灵活,其可以控制新线程和父进程共享的资源和属性。

clone() 系统调用的签名为:

pid_t clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...
            pid_t *ptid, void *tls, pid_t *ctid);

参数:

  • fn: 新线程的执行函数指针。
  • child_stack: 指向新线程的栈顶,用于在新线程中执行函数。
  • flags: 指定新线程与父线程共享哪些资源(如内存、文件描述符等)。
  • arg: 传递给 fn 的参数。
  • 还有一些可选的参数(如 tls, ptid, ctid),用于更细粒度的控制新线程的特性。

线程创建的流程:
线程创建的大体流程如下:

  1. 准备线程属性:
  • pthread_create 首先会根据传入的线程属性(如栈大小、调度策略)准备必要的资源。如果没有指定,使用默认值。
  • 例如,默认情况下,新线程会继承进程的地址空间、文件描述符表、信号处理器等。
  1. 设置栈空间:
  • 为新线程分配栈空间,通常通过映射新的内存区域来完成(使用 mmap() 或现有栈空间)。
  • 栈空间是线程私有的,即每个线程都有自己的栈,以避免不同线程之间的数据混淆。
  1. 调用 clone():
  • pthread_create 通过 clone() 系统调用创建新线程clone() 创建一个新的轻量级进程(LWP),它与调用者共享资源(如地址空间),但有自己的栈和执行上下文。
  • 通过 flags 参数指定哪些资源要共享,常见的标志包括:
    • CLONE_VM: 共享内存空间。
    • CLONE_FS: 共享文件系统信息。
    • CLONE_FILES: 共享文件描述符表。
    • CLONE_SIGHAND: 共享信号处理。
  1. 在新线程中执行函数:
  • clone() 成功后,新线程开始执行 fn 函数,并将传递的 arg 作为参数。
  • 新线程执行函数 fn,直到它返回或显式调用 pthread_exit。
  1. 线程 ID 的管理:
    pthread_create 返回时,会将新创建线程的 ID (pthread_t) 传给调用者。这通常是一个整数(或指针),在系统中唯一标识该线程。
    内核会跟踪这个线程 ID 以及它的相关信息(如状态、栈指针等)。

LWP

LWP是Linux系统中一个重要的概念,一般用来描述系统内核的线程的实现,也是一种轻量化的进程。
 轻量级进程(LWP) 是内核调度的最小单位,LWP通常与用户线程(如使用pthread库创建的线程)一一对应。每个用户线程对应一个LWP,LWP由内核调度和管理。
通过 clone() 系统调用可以创建LWP。clone()允许指定与父进程共享的资源,创建出的子进程就是一个LWP。
 LWP的实现是通过 task_struct 结构体。每个LWP都有一个 task_struct 实例,该结构体包含了调度所需的所有信息,如进程ID(PID)、状态、调度策略等。

pthread_t

pthread_t的概念

pthread_t 是 Pthreads库中的一个数据类型,用来标识一个线程。

当调用pthread_create()时,Pthreads库会为新线程分配一个pthread_t标识符。这个标识符通常在内部对应一个轻量级进程的ID(LWP ID)。

pthread_t 是一个用户级别的标识符。

pthread_t 的实现

pthread_t 的具体实现取决于操作系统和平台。在 Linux 上,通常 pthread_t 被定义为一个 unsigned long int,即一个无符号长整型。这种类型能够唯一标识一个线程。

实际上,pthread_t 在内部可能是一个线程控制块(TCB)的指针,或者是一个可以唯一标识线程的 ID。在 Linux 上,它可能会被直接映射到轻量级进程(LWP)的 ID,或者映射到某种形式的索引结构。

pthread_t 与 LWP 的关系

  • pthread_t 是用户空间的标识符,用户通过它操作线程。每个 pthread_t 对应一个内核中的轻量级进程(LWP)。
  • 当用户调用 pthread 库的函数操作pthread_t 时,底层会通过系统调用与内核交互,对应操作LWP

独立的栈空间

#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdio>
#include <pthread.h>

int g_val = 100;

std::string ToHex(pthread_t tid)
{
    char ch[128];
    snprintf(ch, sizeof(ch), "0x%lx", tid);
    return ch;
}

void *threadRun(void *arg)
{
    std::string name = static_cast<const char *>(arg);
    while (1)
    {
        std::string tid = ToHex(pthread_self());
        std::cout << "I am new thread, my id = " << tid << " val = " << g_val << " &val = " << &g_val << std::endl;
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, threadRun, (void *)"thread-1");

    while (1)
    {
        std::cout << "I am main thread, my val = " << g_val << " &val = " << &g_val << std::endl;
        sleep(1);
    }

    return 0;
}

声明全局变量,分别通过主新线程打印变量值和地址。
在这里插入图片描述
主新线程的g_val值和地址都一样。

那如果在声明变量的时候加上__thread呢?

#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdio>
#include <pthread.h>

__thread int g_val = 100;		//加上了__thread

std::string ToHex(pthread_t tid)
{
    char ch[128];
    snprintf(ch, sizeof(ch), "0x%lx", tid);
    return ch;
}

void *threadRun(void *arg)
{
    std::string name = static_cast<const char *>(arg);
    while (1)
    {
        std::string tid = ToHex(pthread_self());
        std::cout << "I am new thread, my id = " << tid << " val = " << g_val++ << " &val = " << &g_val << std::endl;
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, threadRun, (void *)"thread-1");

    while (1)
    {
        std::cout << "I am main thread, my val = " << g_val << " &val = " << &g_val << std::endl;
        sleep(1);
    }

    return 0;
}

在这里插入图片描述

主新线程的g_val值和地址都不一样,证明不太线程有其独立的栈空间。

管理

pthread_t 是一个用户级别的标识符,而LWP是内核级别的标识符。

  • 内核管理:
     无论是进程还是线程,内核都使用 task_struct 结构体来进行管理。task_struct 是进程和线程在内核中的核心数据结构,包含了所有的管理信息。
  • 用户空间管理:
     pthread 库在用户空间使用自己的数据结构(如 pthread_t 和 TCB)来抽象和管理线程。这些结构为用户提供了线程操作的接口,同时通过系统调用将操作委托给内核。最终,内核中的 task_struct 结构体管理实际的线程调度和执行。

在这里插入图片描述
&emsp因此,pthread 库确实在用户空间维护了一套数据结构来管理线程,而内核则继续使用 task_struct 来维护和管理进程与线程的执行。两者之间通过系统调用进行交互,用户空间的数据结构(如 pthread_t)在本质上是对内核线程的一个抽象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2045830.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

海康VisionMaster使用学习笔记2-相机取图及参数设置

相机取图及参数设置 1. 关联相机-相机管理界面 除了以上两类外,第三方相机都可以通过全局相机进行连接 2. 相机参数设置 相机连接 跨网段IP,枚举 图像缓存数量 实时取流,断线重连 只有支持组播的相机才可以实时取流 触发设置 触发源 LINE0 可以保护电路 LINE2 可配置输入输出…

笔记(day21) 多线程以及锁的概念(超级完整版)

一、 多线程 1.1 程序,进程,线程 程序:一堆命令的集合,完成某个特定任务,是静态的,保存在硬盘中 进程:是程序的一次执行过程,就是把程序载入内存中执行,就是进程,是动态的 线程:是进程进一步细化,是程序内部的一条执行分支 如果一个进程同一时间执行多个线程,就是支持多线程 我…

简单测试AOP五种增强执行时机

1. 目标方法类&#xff0c;spring代理bean Component public class Test {public void test(){System.out.println("test 目标方法");}public void testException(){throw new RuntimeException();} } 2. 配置类 Configuration ComponentScan EnableAspectJAutoPr…

查询满足连续任意30天的全量交易的多个商户

需求说明&#xff1a; 先说表结构把&#xff0c;就是一张订单表存了商户号和其他相关信息&#xff0c;现在要查询这个订单表中以商户为主体的连续交易&#xff0c;也就是每天产生至少一笔订单的商户才算连续&#xff0c;不知道看到的小伙伴有没有什么想法和头绪&#xff0c;在一…

【C++进阶】map与set的封装实践

文章目录 map和setmapmap的框架迭代器operator()operator--()operator()和operator!()operator*()operator->() insertbegin()end()operator[] ()map的所有代码&#xff1a; set的封装迭代器的封装总结 map和set 通过观察stl的底层我们可以看见&#xff0c;map和set是通过红…

ubuntu16.04安装ibus拼音 输入法

前言 开始尝试搜狗输入&#xff0c;发现问题很多&#xff0c;放弃。网上说ibus比较稳定&#xff0c;决定安装ibus输入法。 步骤 安装ibus&#xff0c;使用如下命令, 安装完重启系统&#xff0c;使ibus生效&#xff1b; sudo apt install ibus ibus-pinyin ibus-table ibus-…

maven项目删除pom文件的依赖仍存留在项目中的解决方案【已解决】

前言 使用了pagehelper和mybatisplus的分页插件&#xff0c;起冲突了&#xff0c;想着注释掉pagehelper然后刷新maven&#xff0c;发现一直存留 mlgbz的 试了好多方法&#xff0c;什么缓存乱七八糟的&#xff0c;我以为出bug了 解决

Fiddle抓手机app的包

前言 本次文章讲述的是&#xff0c;fiddle获取手机代理&#xff0c;从而获取手机app的http、https请求&#xff01; 一.下载安装汉化Fiddle 1.点击Fiddler官网下载链接&#xff1a;Download Fiddler Web Debugging Tool for Free by Telerik 2.直接运行&#xff0c;选择自己需…

CUDA C++ 编程指南学习

CUDA C 编程指南 (nvidia.com)https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html 2. 编程模型 2.1. 内核 CUDA C 扩展了 C&#xff0c;允许程序员定义 C 函数&#xff0c;称为内核&#xff0c;当被调用时&#xff0c;N 个不同的 CUDA 线程并行执行 N 次&am…

2023卫星视频综述论文Recent Advances in Intelligent Processing of Satellite Video

2023卫星视频综述论文Recent Advances in Intelligent Processing of Satellite Video 1.摘要2.引言3. 文章的定量分析4 难点与挑战5 方法论系统A. 卫星视频观察的特点B. 卫星视频目标跟踪与运动估计C. 卫星视频目标检测D. 卫星视频超分辨率 (VSR)E. 卫星视频目标分割&#xff…

Idea新建Spring Initializr项目文件哪些可删

​ .gitignore 用git做版本控制时 用这个文件控制那些文件或文件夹 不被提交&#xff08;不用git的话可删除 没影响&#xff09;HELP.md md是一种文档格式 这个就是你项目的帮助文档&#xff08;可删除 没影响&#xff09; mvnw linux上处理mevan版本兼容问题的脚本&#xff0…

企业高性能web服务器

web服务器介绍 Apache HTTP Server&#xff1a;也称为Apache&#xff0c;是一个开源的HTTP服务器&#xff0c;目前是全球使用最广泛的Web服务器 Nginx&#xff1a;Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP服务器 Microsoft Internet Inform…

LVS原理详解及实战部署

一、LVS简介 LVS(Linux Virtual Server)是一种基于Linux的高性能虚拟服务器集群系统&#xff0c;主要用于实现负载均衡。LVS通过Linux内核中的IPVS模块实现了基干!P负载均衡的功能&#xff0c;能够将来自网络的请求分配给后端的多个服务器&#xff0c;从而提供高可用性和伸缩性…

Linux系统编程:线程 3:信号量

1.信号量的概念 信号量是线程间有顺序的协调工作&#xff0c;信号量 (个数) 反映的是资源的数量&#xff0c;信号量起到锁的效果&#xff1b; 2.信号量的机制 &#xff08;1&#xff09;信号量描述可使用资源的个数&#xff1b; &#xff08;2&#xff09;p操作&#xff0c…

第二证券:全球首款双人互动剧上线 暑期游戏持续升温

全球首款双人互动剧上线 全球首款双人互动剧《谍影成双》现已在全球游戏渠道Steam、微信小程序、QQ小程序同步上线。根据上海影视乐园官方大众号&#xff0c;该作是2023年度爆款互动剧《飞越13号房》制造团队互影科技的全新著作。 2023年被称为互动剧的元年&#xff0c;“互动…

python学习day15地图、柱状图

地图、柱状图 地图示例 柱状图XY轴反转小结 时间线柱状图自动播放小结 动态柱状图sort排序练习动态柱状图 地图 from pyecharts.charts import Map mapMap() data[(北京市,999),(上海市,133),(河南省,123),(西藏自治区,123),(吉林省,12), ]map.add("地图",data,"…

ElasticSearch数据建模

文章目录 如何处理关联关系避免过多字段避免正则/通配符/前缀查询避免空值引起的聚合不准为索引的Mapping加入Meta 信息 如何处理关联关系 Object: 优先考虑反范式&#xff08;Denormalization&#xff09; Nested: 当数据包含多数值对象&#xff0c;同时有查询需求 Child/Pa…

SAP BAPI for Tcode SM12

注意&#xff1a;ENQUE_READ 和 ENQUE_READ2 的table ENQ是两个不同的结构 想通过 ENQUE_READ2 读取结构然后去删除 ENQUE_DELETE的 要注意不能直接用 要用 ENQUE_CONVERT_SEQG7_TO_SEQG3 进行转换 FUNCTION ENQUE_CONVERT_SEQG7_TO_SEQG3. *"-----------------------…

[000-01-030].第2节 :Zookeeper本地安装

1.Zookeeper下载地址 1.Zookeeper官网地址 2.会显示Zookeeper的一些版本 2.Zookeeper本地模式安装&#xff1a; 2.1.Zookeeper安装前准备 1.在Centos7虚拟机中安装jdk8 2.2.Zookeeper安装过程&#xff1a; 1.下载zookeeper压缩版本&#xff0c;解压放在opt/moduel目录下…

为啥90%设计师素材整理文件夹都是无效的?

大家好&#xff0c;今天我想和大家分享一下我在使用千鹿设计助手软件之前的图片管理经历&#xff0c;以及千鹿给我带来的巨大变化。 正文&#xff1a; 大家好&#xff0c;今天我想和大家分享一下我在使用千鹿软件之前的图片管理经历&#xff0c;以及千鹿给我带来的巨大变化。 …