深入Linux轻量级进程管理:线程创建、线程ID解析与进程地址空间页表探究

本文主要是介绍深入Linux轻量级进程管理:线程创建、线程ID解析与进程地址空间页表探究,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

🍑个人主页:Jupiter.
🚀 所属专栏:Linux从入门到进阶
欢迎大家点赞收藏评论😊

在这里插入图片描述

在这里插入图片描述

目录

  • `🚲Linux线程控制`
    • `🐏POSIX线程库`
    • `🐕创建线程`
      • `🐟指令查看轻量级进程`
          • `指令:ps -aL`
    • `🐒线程ID及进程地址空间布局`
            • *pthread_t 到底是什么类型呢?*
      • `🦔__thread与线程的局部存储`


🚲Linux线程控制

🐏POSIX线程库

在Linux中,没有线程的概念,只有轻量级进程的概念,所以Linux系统只提供了轻量级进程的系统调用,没有线程相关的系统调用,但是用户不知道轻量级进程的概念,只知道线程和进程,所以Linux将轻量级进程的系统调用进行封装,转成线程相关的接口语义提供给用户,就形成了pthread库

  • 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”开头的。
  • 要使用这些函数库,要通过引入头文<pthread.h>
  • 链接这些线程函数库时要使用编译器命令“-lpthread”选项。

🐕创建线程

  • 功能:创建一个新的线程

  • 原型
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);

  • 参数

    • thread:返回线程ID
    • attr:设置线程的属性,attr为NULL表示使用默认属性
    • start_routine:是个函数地址,线程启动后要执行的函数
    • arg:传给线程启动函数的参数(可以是对象等等)
    • 返回值:成功返回0;失败返回错误码
  • 错误检查:

    • 传统的一些函数是,成功返回0,失败返回-1,并且对全局变量errno赋值以指示错误。
    • pthreads函数出错时不会设置全局变量errno(而大部分其他POSIX函数会这样做)。而是将错误代码通过返回值返回pthreads同样也提供了线程内的errno变量,以支持其它使用errno的代码。对于pthreads函数的错误,建议通过返回值判定,因为读取返回值要比读取线程内的errno变量的开销更小。

注意:新线程和主线程谁先运行?这是未知的。

示例代码:

#include <iostream>
#include <unistd.h>
#include <pthread.h>void *routine(void *name)
{std::cout << "i am new thread,name:" << (char *)name << std::endl;sleep(1);return nullptr;
}
int main()
{pthread_t tid;pthread_create(&tid, nullptr, routine, (void *)("thread-1"));while (true){std::cout << "i am process,pid:" << getpid() << std::endl;sleep(1);}return 0;
}

运行结果:

🐟指令查看轻量级进程

指令:ps -aL

根据上面的结果可知:他们的pid一样,所以属于同一个进程,而且可知:OS在进行调度的时候,用的是LWP进行调度的。(因为pid可能一样,不能唯一性标识)

🐒线程ID及进程地址空间布局

  • pthread_ create函数会产生一个线程ID,存放在第一个参数指向的地址中。

  • 前面讲的线程ID属于进程调度的范畴。因为线程是轻量级进程是操作系统调度器的最小单位,所以需要一个数值来唯一表示该线程。

  • pthread_ create函数第一个参数指向一个虚拟内存单元,该内存单元的地址即为新创建线程的线程ID,属于NPTL线程库的范畴。线程库的后续操作,就是根据该线程ID来操作线程的。

线程库NPTL提供了pthread_ self函数,可以获得线程自身的ID

  • pthread_t pthread_self(void);
pthread_t 到底是什么类型呢?
  • 取决于实现。对于Linux目前实现的NPTL实现而言,pthread_t类型的线程ID本质就是一个进程地址空间上的一个地址

  • 线程的管理库维护,即描述线程的结构体与管理线程的数据结构(类似于数组)就在库里面的,其中pthread_t tid即是描述tid线程结构体的起始地址

  • 线程的栈与局部存储是在库中维护的。虽然栈是线程独立的,但是其他线程也是可以访问的。

示例代码:

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
std::string ToHex(pthread_t tid)   //将id转换为十六进制
{char buff[64];snprintf(buff, 64, "0x%lx", tid);return buff;
}void *routine(void *name)
{while (true){sleep(1);std::cout << "i am new thread,name:" << (char *)name << "  my tid is :" << ToHex(pthread_self()) << std::endl;}return nullptr;
}
int main()
{pthread_t tid;pthread_create(&tid, nullptr, routine, (void *)("thread-1"));while (true){std::cout << "i am process,pid:" << getpid() << "  new thread id:" << ToHex(tid) << std::endl;sleep(1);}return 0;
}

运行结果:
在这里插入图片描述

🦔__thread与线程的局部存储

  • __thread 是 C 和 C++ 中用于声明线程局部存储的一个关键字(或属性,具体取决于编译器和平台)。它告诉编译器或链接器,被 __thread 修饰的变量是每个线程私有的,即每个线程都有该变量的一个独立实例,这些实例之间互不影响。如:__thread int tls_variable = 0; 一般对于全局变量使用。
    示例代码:
#include <pthread.h>  
#include <stdio.h>  // 声明一个线程局部变量  
__thread int tls_variable = 0;  void* thread_function(void* arg) 
{  tls_variable = (int)arg; // 每个线程都会修改它自己的 tls_variable 副本  printf("Thread %ld has tls_variable = %d\n", (long)pthread_self(), tls_variable);  return NULL;  
}  int main() {  pthread_t threads[2];  // 创建两个线程,每个线程将接收到一个不同的参数  pthread_create(&threads[0], NULL, thread_function, (void*)1);  pthread_create(&threads[1], NULL, thread_function, (void*)2);  // 等待两个线程完成  pthread_join(threads[0], NULL);  pthread_join(threads[1], NULL);  return 0;  
}

这篇关于深入Linux轻量级进程管理:线程创建、线程ID解析与进程地址空间页表探究的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1140738

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal