【Linux】线程

news2024/12/27 1:56:25

1.理解地址空间和页表

1.地址空间是进程能够看到的资源窗口

2.页表决定进程真正拥有的资源情况

3.合理的对地址空间和页表进行资源划分就可以对一个进程的所有资源进行划分:过地址空间分为栈区、堆区…通过页表映射到不同的物理内存。

在32位平台下,一共有2^32个地址,也就意味着有2^32个地址需要被映射。地址空间一共有2的32次方个地址,每个地址单位都是1字节,OS是如何做到从虚拟地址到物理地址做转换的呢?

 其中页目录项是一级页表,页表项是二级页表。虚拟地址转成物理地址:32位的虚拟地址以10,10,12的二进制构成,页表不止一张,页目录:页目录中存放的是页表的地址,根据虚拟地址的前十位确定所需页表的起始地址,页表:每一个页表的条目项为2的10次方个,页表中存的是页框的起始物理地址,根据中间的十位确定页框的起始位置,剩下的12位虚拟地址是偏移量,根据页框的起始位置开始往下偏移这个偏移量就找到了对应的物理内存。OS中把物理内存一块块的数据框称为页框,磁盘上编译形成可执行程序的时候,也被划分成一个个4KB的区域称为页帧。当内存和磁盘进行数据交换时也就是以4KB大小为单位进行加载和保存的,这个偏移量刚好与页框的大小是等价的(4KB等于2的12次方字节)。

2.线程概念

在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列 ”。一切进程至少都有一个执行线程;线程在进程内部运行,本质是在进程地址空间内运行在Linux系统中CPU看到的PCB都要比传统的进程更加轻量化。透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流。

1.线程在进程的内部运行线程在进程的地址空间内部运行,拥有该进程的一部分资源,我们可以通过地址空间+页表的方式对进程进行资源划分。 2.站在CPU的角度,每一个PCB都可以叫做轻量级进程3.Linux线程是CPU调度的基本单位,进程是承担系统资源分配的基本单位,进程是申请资源,线程是向进程要资源4.Linux中没有真正意义上的线程,是由PCB模拟实现的。OS无法直接创建线程,而是只提供创建轻量级进程的窗口。5.PCB模拟线程,为PCB编写的结构与算法都能进行复用,不用单独为线程创建调度算法,这样做的好处是维护成本低,可靠性高。

3.创建线程

因为OS没有创建线程的接口,只能通过第三方的库<pthread.h>提供创建建轻量级进程的接口

 因为只用的是第三方的库,所以在编译的时候要指明链接的库

#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<string>
using namespace std;

void* start_routine(void* args)
{
    string name=static_cast<const char*>(args);  //安全的类型转换
    while(true)
    {
        cout<<"i am new thread, name: "<<name<<endl;
        sleep(1);
    }

    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid,nullptr,start_routine,(void*)"new thread");
               //线程id  新线程属性   线程执行的函数    传给线程执行函数的参数   
    while(true)
    {
        cout<<"我是主线程......"<<endl;
        sleep(1);
    }
    return 0;
}

 结果可以看到主线程和新线程是交替执行的,CPU是以什么为标识符来调度这两个执行流的呢?

ps -aL  //查看轻量级进程

 PID为9764的两个轻量级进程是进程的ID 与进程ID相同的LWP是主线程的ID,LWP为9765的轻量级进程是我们创建出来的新线程的ID。----->CPU调度时是以LWP为标识符的! 

一个进程创建了线程,几乎所有的资源都是线程共享的,但是线程也是有自己的私有内部属性

什么资源是线程私有的呢?

1.PCB的属性是私有的

2.私有的上下文结构               //每个线程都是要被调度和切换的,如果时间片内线程的代码没有跑完,此时线程的上下文就需要被保存

3.每个线程都有自己独立的栈结构         //线程内部的局部变量需要被保存,保存在每个线程独立的栈结构里

总结之前的知识点:

1.线程是进程内部的执行流

2.进程承担分配系统的资源,创建线程知识创建了PCB

3.一个进程内部至少有一个执行流

4.CPU看到的PCB都是轻量级进程

4.线程的优缺点

优点

1.创建一个新线程的代价要比创建一个新进程小得多
2.与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多(进程间切换,需要切换页表、虚拟空间、切换PCB、切换上下文,而线程间切换,页表和虚拟地址空间就不需要切换了,只需要切换PCB和上下文,成本较低)
3.线程占用的资源要比进程少很多
4.能充分利用多处理器的可并行数量
5.在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
6.计算密集型应用(CPU,加密,解密,算法等),为了能在多处理器系统上运行,将计算分解到多个线程中实现
7.I/O密集型应用(外设,访问磁盘,显示器,网络),为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作

缺点

性能损失:一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。
健壮性降低:编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
编程难度提高:编写与调试一个多线程程序比单线程程序困难得多

5.线程终止

1.线程调用的函数return了,这个线程就终止了

2.在线程的内部调用pthread_exit(nullptr),线程就终止了。

3.exit(0)不能终止线程是用来终止进程的,任何一个执行流调用exit(0)这个进程就终止了,进程终止了线程也就都退出了。

6.线程等待

线程也是需要被等待的,如果不等待就会造成类似僵尸进程的问题----内存泄漏

等待是为了:1.回收新线程对应的PCB等内核资源,防止内存泄漏2.回收线程对应的退出信息

void* start_routine(void* args)
{
    string name=static_cast<const char*>(args);
    int cnt=3;
    while(cnt--)
    {
        cout<<"i am new thread, name: "<<name<<endl;
        sleep(1);
    }

    return (void*)10086;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid,nullptr,start_routine,(void*)"new thread");
    int c=4;
    while(c--)
    {
        cout<<"我是主线程......"<<endl;
        sleep(1);
    }
    void* ret=nullptr;
    pthread_join(tid,&ret);
    cout<<"main join success exit number:"<<(long long)ret<<endl;
    return 0;
}

void** retval:输出型参数,主要用来获取线程函数结束时返回的退出结果。之所以是void**,是因为如果想作为输出型结果返回,因为线程函数的返回结果是void*,而要把结果带出去就必须是void**

没有看到线程退出时对应的退出信号:这是因为线程出异常收到信号,整个进程都会退出,所以退出信号要由进程来关心,所以pthread_join默认会认为函数会调用成功,不考虑异常问题,异常问题是进程该考虑的问题

  7.线程分离

线程是可以等待的,等待的时候,是join的等待的,阻塞式等待。而如果线程我们不想等待:不要等待,该去进行分离线程处理。

默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成内存泄漏

而如果我们不关心线程的返回值,join是一种负担,这个时候我们可以告诉OS,当线程退出时,自动释放线程资源,这种策略就是线程分离。

int pthread_detach(pthread_t thread);

线程分离函数可以由新线称和主线程来调用,但是这里推荐分离操作由主线程来完成因为创建线程后主线程和新线程不确定谁先运行,所以可能会有这样的场景,当我们创建主线程之后,还没有执行新线程的pthread_detach,而主线程直接去等待了,也就是新线程还没来得及分离自己,也就是分离的太慢了,最后主线程直接去等待了。

void* start_routine(void* args)
{
    //pthread_detach(pthread_self());  线程得到自己的tid然后做分离
    string name=static_cast<const char*>(args);
    int cnt=3;
    while(cnt--)
    {
        cout<<"i am new thread, name: "<<name<<endl;
        sleep(1);
    }

    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid,nullptr,start_routine,(void*)"new thread");
      // sleep(2);
    pthread_detach(tid);
    int c=4;
    while(c--)
    {
        cout<<"我是主线程......"<<endl;
        sleep(1);
    }
   
    return 0;
}

8.理解线程id和地址空间的关系

pthread_create函数会产生一个线程id,存放在第一个参数指向的地址中

<pthread.h>库帮助我们建立线程,这个库可以叫做原生线程库,当我们创建一个新的线程后,在pthread库中就创建了一个关于该线程属性集合的对象,同时创建一个轻量级进程。pthread_t类型的线程ID,本质 就是一个进程地址空间上的一个地址。通过这个地址就可以访问到对应轻量级进程的结构体,结构体中包含线程的一些私有属性。

Linux用户级线程:内核级轻量级进程 = 1:1

 

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

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

相关文章

Mysql学习(十一) -- 常见问题处理

1. MySQL数据库cpu飙升的话你会如何分析 重点是定位问题。 使用top观察mysqld的cpu利用率 切换到常用的数据库使用show full processlist;查看会话观察是哪些sql消耗了资源&#xff0c;其中重点观察state指标定位到具体sql pidstat 定位到线程在PERFORMANCE_SCHEMA.THREADS中…

Nevercenter CameraBag Pro照片滤镜软件 v2023.2.0

Nevercenter CameraBag Pro是一款照片滤镜工具&#xff0c;它可以让您轻松地添加各种效果和样式到您的照片中。该软件可以模拟不同类型的相机、胶片和滤镜&#xff0c;让您的照片呈现出具有艺术感的效果。 CameraBag Pro提供了多达200种不同的滤镜和效果&#xff0c;包括黑白、…

自然机器人最新发布:智能流程助手,与GPT深度融合

ChatGPT自2022年11月上线后就受到现象级地广泛关注&#xff0c;5天时间用户就已经突破百万&#xff0c;仅2个月时间月活用户就突破1亿&#xff0c;成为史上增速最快的消费级应用&#xff0c;远超TikTok、Facebook、Google等全球应用。它展现了类似人类的语言理解和对话交互能力…

java+Servlet家庭个人理财财务系统

目录 1 引言 1 1.1 选题背景 1 1.2 国内外研究现状 1 1.3 课题研究意义 1 1.4 设计目标 2 2 系统关键技术研究 3 2.1 JSP技术简介 3 2.2 Servlet技术简介 4 2.3 My Eclipse简介 7 2.4 系统运行平台 8 3 系统需求分析 9 3.1 总体需求 9 3.2…

【在Github上寻找安装ROS软件包】

【在Github上寻找安装ROS软件包】 1. Github网站搜索2. 工作空间3. WPR系列机器人仿真工具3.1 系统版本3.2 复制https git下载链接3.3 安装依赖项:3.4 编译工作空间3.5 载入工作空间的环境配置3.6 运行编译的ros程序3.6 运行rqt控制的ros程序3.7 提前初始化source文件 项目地址…

C语言学习(四)

char类型数组 字符串&#xff0c;由一个或多个字符组成的序列就做字符串。双引号不是字符串的一部分&#xff0c;只是告诉双引号里的内容是字符串&#xff0c;C语言中没有专门储存字符串的变量类型&#xff0c;字符串都被存储在char类型的数组中。数组由连续的储存单元组成&…

一文搞懂Redis事务~

先说结论&#xff1a; Redis 的事务模式具备如下特点&#xff1a; 保证隔离性&#xff1b;无法保证持久性&#xff1b;具备了一定的原子性&#xff0c;但不支持回滚&#xff1b;一致性的概念有分歧&#xff0c;假设在一致性的核心是约束的语意下&#xff0c;Redis 的事务可以…

Visual Studio 2019 的快捷键和视图布局使用

文章目录 常见快捷键视图布局 常见快捷键 Ctrl Shift / : 将选中的多行注释&#xff0c;或光标所在行 的单行注释。取消注释 这是此快捷键。 CtrlShift Enter : 重启一行&#xff0c;是从当前行的下面&#xff0c;重启一行。 Ctrl Enter : 重启一行&#xff0c;是从当前行的…

javascript中this指向问题

JavaScript中this指向问题 1、this指向window的情况 对于非箭头函数情况下&#xff0c;谁调用就指向谁,如果函数在全局作用域下调用,里面的this就是window。 在全局作用域下&#xff0c;this window function sum() {console.log(this); }sum(); // windowconsole.log(this…

中电金信:生成式AI热潮下,文本智能走向何方?

突破通用人工智能场景&#xff0c;生成式AI正在向全行业应用进攻。 一个脑筋急转弯&#xff0c;几个月前ChatGPT是这样回答的&#xff1a; 然而&#xff0c;仅仅几个月的迭代&#xff0c;它的回答却让人出乎意料。 看似调侃的对比背后实则是无数次模型训练的支撑。基于数据的激…

[Gitops--3]项目代码发布案例Argocd+Gitlab-Runner

项目代码发布案例ArgocdGitlab-Runner 1. 项目文件 demo项目放在gitee上需要自取 git clone https://gitee.com/qqmiller/godemo.git1.1 项目代码 apidemo.go package mainimport ("github.com/gin-gonic/gin""net/http" )func main() {r : gin.Defau…

GPT模型支持下的Python-GEE遥感云大数据分析、管理与可视化技术应用

随着航空、航天、近地空间等多个遥感平台的不断发展&#xff0c;近年来遥感技术突飞猛进。由此&#xff0c;遥感数据的空间、时间、光谱分辨率不断提高&#xff0c;数据量也大幅增长&#xff0c;使其越来越具有大数据特征。对于相关研究而言&#xff0c;遥感大数据的出现为其提…

Bugku——应急加固1

来打一下bugku的应急加固靶场&#xff0c;靶场链接&#xff1a;https://ctf.bugku.com/ctfplus/detail/id/2.html 启动环境 1、JS劫持域名 直接访问ip地址&#xff0c;发现是xxx学院二手交易市场&#xff0c;随后被劫持跳转到了一个博客页面。 博客地址就是第一个flag&…

记录踩的坑:python gdal 重采样+坐标系转换

源数据&#xff1a;1/0 二值数据&#xff0c;30m 分辨率&#xff0c;WGS_1984_UTM_Zone_53N 坐标系&#xff0c;东北区域。 目标&#xff1a;将源数据制成与 MODIS tile 的坐标系&#xff08;Sinusoidal&#xff09;、分辨率&#xff08;463.3127165m&#xff09;都一致的tif。…

padans关于数据处理的杂谈

情况&#xff1a;业务数据基本字段会有如下&#xff1a; Index([时间, 地区, 产品, 字段, 数值], dtypeobject)这样就会引发一个经典“三角不可能定理”&#xff0c;如何同时简约展现分时序、分产品、分字段数据。&#xff09;一般来说&#xff0c; 1、时序为作为单独的分类&…

10KV高压开关柜怎么进行无线测温

摘要&#xff1a;文章提出了一种用于小车式开关柜的无线测温系统&#xff0c;包括设于小车动触头套管上的温度传感器、环绕设于小车动触头上的电流传感器&#xff0c;温度传感器及电流传感器均分别连接有数据接收处理器&#xff0c;数据接收处理器电连接有设于小车式开关柜上的…

实例分享| anyRTC 部署南京某区城市运行“一网统管”综合调度系统

近年来国家城运中心&#xff0c;加大了对城运信息化系统的建设的投入&#xff0c;通过对城运的信息化建设&#xff0c;提升城市服务能力和现代化管理水平、进一步增强城市竞争力、让信息化切实做到为人民服务的根本能力。 南京市首先提出城市运行”一网统管“的计划&#xff0…

R语言地理空间分析、可视化及模型预测

随着地理信息系统&#xff08;GIS&#xff09;和大尺度研究的发展&#xff0c;空间数据的管理、统计与制图变得越来越重要。R语言在数据分析、挖掘和可视化中发挥着重要的作用&#xff0c;其中在空间分析方面扮演着重要角色&#xff0c;与空间相关的包的数量也达到130多个。在本…

Failed to resolve: com.github.adrielcafe:ffmpeg-android-java:2a627f6ecd

背景 项目中有引用 AndroidAudioConverter&#xff0c;引入方式&#xff1a; implementation com.github.adrielcafe:AndroidAudioConverter:0.0.8 gradle同步及编译代码都会报错&#xff1a; Failed to resolve: com.github.adrielcafe:ffmpeg-android-java:2a627f6ecd 原…

带你浅谈下Quartz的简单使用

Scheduler 每次执行&#xff0c;都会根据JobDetail创建一个新的Job实例&#xff0c;这样就可以规避并发访问的问题&#xff08;jobDetail的实例也是新的&#xff09; Quzrtz 定时任务默认都是并发执行&#xff0c;不会等待上一次任务执行完毕&#xff0c;只要间隔时间到就会执…