1. 线程

1. 线程是一个进程内部的控制序列

2. 线程在进程内部运行,本质是在进程地址空间内运行

3. 进程:承担分配系统资源的基本实体

    线程:CPU调度的基本单位

4. 线程在进程地址空间内运行

    进程访问的大部分资源都是通过地址空间访问的

5. 在硬件CPU视角:线程是轻量级进程

     Linux操作系统视角:执行流

     执行流 <= 进程

6. 将资源合理分配给每一个执行流,就形成了线程执行流

7. 一切进程至少都有一个执行线程


总结:

1. 线程可以采用进程来模拟

2. 对资源的划分本质是对地址空间虚拟地址范围的划分。虚拟地址就是资源的代表

3. 函数就是虚拟地址(逻辑地址)空间的集合,就是让线程未来执行ELF程序的不同函数

4. linux的线程就是轻量级进程,或者用轻量级进程模拟实现的

5. 如果把家庭比作进程,那么家庭的每个成员就都是线程

进程强调独占,部分共享(通信的时候)

线程强调共享,部分独占


4KB内存与页框:

物理内存以4KB为单位被划分成一个一个的页框

在进行I/O操作时,数据也是以4KB为单位在内存和磁盘间交换(程序需要读取磁盘数据时也是以4KB大小的块来读取)

要管理这些4KB的页框,也是先描述再组织

申请物理内存是在做什么?

1.查数组,改page(页)

2.建立内核数据结构的对应关系

struck page是一个自定义描述物理内存中页的结构体

struct page mem[1048576];

声明了一个包含1048576个类型为struct page的元素的mem数组,每个page都有下标

4GB=4*1024*1024 KB

4*1024*1024KB/4KB = 1048576

每个page的起始物理地址就在独立,具体物理地址=起始物理地址+页(4KB)内偏移

没有使用的page标志位为0


划分地址空间本质就是划分虚拟地址

在cpu视角全部都是轻量级进程

OS管理的基本单位是4KB


页表(本质是一张虚拟到物理的地图)的地址转换

虚拟地址(逻辑地址) 转化为物理地址

32位的数字

0000000000 0000000000 000000000000                        
[0,1024)        [0,1024)             [0,4096]

CR3寄存器读取页目录起始位置,根据一级页号查页目录表

前10个bit位的缩影查到页目录

页目录里存储的是下一级页表的地址,每一项对应一个二级页表,定位到下一级页表的位置

页目录中的项可以理解为一种指针

二级页表里面存储的是物理页框的地址,用于实现虚拟地址和物理地址间映射的关键

低12位为页内偏移

4KB页面大小意味着每个页面有4096个字节单位,12位二进制数可表示为2^12 = 4096 个不同地址,可以用低12位去充分覆盖一个页框的整个范围,可唯一标识页面内的每个字节单元

先查到虚拟地址对应的页框,根据虚拟地址的低12位作为页内偏移访问具体字节


一些细节:

1. 内存申请->查找数组->找到没有被使用的page(标志位为0)->page

index(索引)->物理页框地址

2. 写实拷贝,缺页中断,内存申请等,背后都可能要重新建立新的页表和建立映射关系的操作

3. 进程,一张页目录+n张页表构建的映射关系,虚拟地址是索引,物理地址页框是目标

物理地址=页框地址+虚拟地址(低12位)


线程的深刻理解

执行流看到的资源是在合法情况下拥有的合法虚拟地址,虚拟地址就是资源的代表

虚拟地址空间本质:进行资源的统计数据还和整体数据

资源划分:本质就是地址空间划分

资源共享:本质就是虚拟地址的共享

线程进行资源划分:本质是划分地址空间,获得一定范围的合法虚拟地址,在本质,就是划分页表

线程进行资源共享:本质是对地址空间的共享,在本质就是对页表条目的共享


申请内存也就是申请地址空间

越界不一定报错


优点:

线程切换:

线程之间的切换需要OS做的工作比进程要少很多

线程切换虚拟地址空间依然是相同的

线程切换时不用对CR3寄存器进行保存
线程切换不会导致缓存失效

进程切换:

指针指向我们选中的进程,OS想知道当前进程是谁,找到该指针,优化到cpu寄存器中

进程切换=>cpu硬件上下文切换

会导致TLB和Cache失效,下次运行,需要重新缓存

线程占用的资源比进程少?线程拿到的资源本身就是进程的一部分,线程是更轻量化的


2. 进程VS线程

进程是资源分配的基本单位

线程是调度的基本单位

线程共享进程数据,但也拥有自己的一部分数据

1.线程ID

2.一组寄存器,线程的上下文数据

3.栈

4.erno

5.信号屏蔽字

6.调度优先级


3. linux 线程控制

创建线程

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);//thread :返回线程id
//attr:设置线程属性
//start_routine:是个函数地址,线程启动后要执行的函数
//arg:传给线程启动函数的参数

线程创建好之后,新线程要被主线程等待(类似僵尸进程的问题,内存泄漏)

代码:

 PID:进程ID

LWP:  轻量级进程ID

这意味着进程内有多个线程,每个线程对应一个LWP号

CPU调度的时候,看轻量级进程lwp

1.关于调度的时间片问题:时间等分给不同的线程

2.任何一个线程崩溃,都会导致整个进程崩溃

线程tid:不直接暴露lwp概念

#include <iostream>
#include <cstdio>
#include <string>
#include <unistd.h>
#include <pthread.h>void showtid(pthread_t &tid)
{printf("tid: 0x%lx\n",tid);
}
std::string FormatId(const pthread_t &tid)
{char id[64];snprintf(id, sizeof(id), "0x%lx", tid);return id;
}
void *routine(void *args)
{std::string name = static_cast<const char*>(args);pthread_t tid = pthread_self();int cnt = 3;while(cnt){std::cout << "我是一个新线程: my name: main thread "  << " 我的Id:  " << FormatId(tid) << std::endl;sleep(1);cnt--; }return nullptr;
}int main()
{pthread_t tid;//tid变量用于存储新创建进程的标识符int n = pthread_create(&tid, nullptr, routine, (void*)"thread-1");(void)n;showtid(tid);int cnt = 3;while(cnt){std::cout << "我是main线程: my name: main thread " << " 我的Id:  " << FormatId(pthread_self()) << std::endl;sleep(1);cnt--; }pthread_join(tid,nullptr);//等待进程结束return 0;
}

main函数也有自己的线程id


pthread库,把创建轻量级进程封装起来,给用户提供一批创建线程的接口

linux线程实现是在用户层实现的,我们称之为用户级线程

pthread:原生线程库

C++的多线程,在linux下,本质是封装了pthread库,在windows下封装windows创建线程的接口

linux系统,不存在真正意义上的线程,他所谓的概念,使用轻量级进程模拟的,但OS中,只有轻量级进程,所谓的模拟线程是我们的说法,linux只会给我们提供创建轻量级进程的系统调用


pthread_exit函数

线程终止


pthread_cancel

取消一个执行中的线程

取消的时候一定要保证线程已经启动


pthread_join

等待线程结束

资源回收,线程终止时,系统不会自动回收线程资源,直到有其他线程调用该函数,目标线程的资源会被彻底释放。

//thread:要等待的线程id

//retval:二级指针,用于存储目标线程的返回值

pthread_join() 函数必须由其他线程调用,用于回收目标终止线程的资源

只能由当前线程以外的其他线程调用。例如:
主线程可以调用 pthread_join() 回收子线程的资源
子线程 A 可以调用 pthread_join() 回收子线程 B 的资源

通过函数参数指定要回收的目标线程 ID(tid)


线程分离

线程分离是一种管理线程资源的机制,当线程被设置为分离状态时,它终止后会自动释放所有资源,不需要有其他线程调用pthread_join来回收资源

线程的状态:1.Joinable 可结合的 新创建的线程是可结合的,需要对其进行pthread_join操作来回                           收资源,避免资源泄露

                      2.Detached 分离的

------------------------------------------------------------------------------------------------------------------------------------------------------------

linux没有真正的线程,他是用轻量级进程模拟的

os提供的接口,不会直接提供线程接口

在用户层,封装轻量级进程形成原生线程库(用户级别的库)

linux所有线程,都在库中

线程的概念是在库中维护的,在库内部就一定会存在多个被创建好的线程,库管理线程也是先描述再组织

                   pthread_create()

struct tcb

        //线程应该有的属性

        线程状态

        线程id

        线程独立的栈结构

        线程栈大小

线程自己的代码区可以访问到pthread库内部的函数或数据

linux所有线程都在库中


显示器文件本身就是共享资源

拿到新线程的退出信息

线程测试

线程能够执行进程的一部分

创建多线程


为什么是9?给每个线程第一传id,大家的地址都一样,所有线程参数指向的空间都是同一个,每创建一个进程都要覆盖式改这个id,创建的这个id会让所有线程都看到,拿到的都是同一个地址,指向的是同一个64位的空间,所以进行对应的写入时就把上一次的覆盖了


每一次循环要给每一个线程申请一段堆空间,这个堆空间虽然也是共享的,但只有改=该线程知道空间的起始地址

创建访问线程的本质就是访问用户级别的库


描述线程的管理块

                                                          pthread库在内存中


只需要描述我们线程有关的id信息

创建一个描述线程的管理块,有三部分构成,返回时,返回的id地址就是这个块的起始地址

需要jion,因为线程结束时,只是函数结束了,但是在库中线程管理块并没有结束

tid(退出的线程管理块的起始地址/线程在库中,对应的管理快块的虚拟地址)和ret(曾经线程退出时的结果)就拿到整个线程退出时的退出信息,再把该线程的管理块全部释放,得到返回结果同时解决内存泄漏问题

在自己的代码区里调create(),其实是在动态库内部创建描述该线程的管理块,管理块的开头是线程tcb,里面包含了线程的相关信息,tcb里包含了void *ret字段。当当前线程运行的时候,运行结束会把返回值拷贝到自己线程控制块的void *ret。新主线程都共享地址空间,只要拿到起始虚拟地址,就可以拿到退出线程的控制块

每个线程都有自己独立的栈空间


clone是用于创建进程/线程的函数,可以看作是fork的升级版

 #define _GNU_SOURCE#include <sched.h>int clone(int (*fn)(void *), void *stack, int flags, void *arg, .../* pid_t *parent_tid, void *tls, pid_t *child_tid */ );

fn:子进程/线程的入口函数

linux所有线nn

linux用户级线程:内核级LWP = 1:1

主线程和新线程谁先运行是不确定的

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt Quick 与 QML(三)qml中的基础控件

一、基础控件 控件名称‌‌功能描述‌‌示例代码‌‌Rectangle‌基础绘图控件&#xff0c;创建矩形区域Rectangle {width: 100; height: 100<br> color: "red"; radius: 5}‌Text/Label‌文本显示控件Text {text: "Hello World";<br> font.pi…

Redis实现消息队列全解析:从基础到高级应用实战

目录 一、Redis作为消息队列的优势与局限 1.1 核心优势 1.2 适用场景 1.3 局限性及解决方案 二、Redis消息队列实现方案对比 三、List实现基础消息队列 3.1 生产者实现原理 3.2 消费者实现原理 3.3 可靠性增强&#xff1a;ACK机制 四、Pub/Sub实现发布订阅 4.1 消息发…

Windows应用商店中的国学启蒙教育应用

国学启蒙是中国传统文化教育的重要组成部分&#xff0c;主要以经典诵读、传统礼仪、历史故事等内容为载体&#xff0c;向儿童传递中华文化的核心价值观。帮助孩子建立文化认同感&#xff0c;培养良好的道德观念和行为习惯。通过学习古代圣贤的言行&#xff0c;儿童可以初步理解…

安科瑞UL认证ADL3000-E/C导轨表:工商业储能领域的智能之选

一、产品简介 ADL3000-E/C是安科瑞针对电力系统、工矿企业、公用设施的电力监控及能耗统计、管理需求而精心设计的一款智能仪表。该电能表具有精度高、体积小、安装方便等显著优点&#xff0c;为工商业储能系统的智能化管理提供了强有力的技术支持。 功能特性 测量与计量功能…

条件向量运算与三元表达式

在工程计算和数学建模中&#xff0c;我们经常需要根据条件动态选择不同的向量运算方式。这种需求在动力学系统、控制理论和计算机图形学中尤为常见。本文将探讨如何通过 Python 的三元表达式结合 SymPy 符号计算库&#xff0c;实现条件向量运算的高效解决方案。 我们从定义两…

文档开发组件Aspose旗下热门产品优势及应用场景介绍

✨Aspose 是什么&#xff1f; Aspose 是全球领先的文档处理组件厂商&#xff0c;主打一个字&#xff1a;全。 &#x1f4cc; 支持超 100 种文档/图像格式 &#x1f4cc; 覆盖 Word、Excel、PDF、PPT、OCR、BarCode、Email 等模块 &#x1f4cc; 支持 .NET、Java、Python、C、N…

龙虎榜——20250618

上证指数缩量长下影小阳线&#xff0c;个股下跌超3300只&#xff0c;总体护盘的板块表现相对更好。 深证指数缩量收小阳线&#xff0c;横盘震荡已有4天&#xff0c;等待方向选择。 2025年6月18日龙虎榜行业方向分析 1. 半导体 代表标的&#xff1a;沪电股份&#xff08;高阶P…

layui和vue父子级页面及操作

最近在老项目里面添加一些页面&#xff0c;项目太老只能在原有的项目基础和插件上添加代码 html //表格 <table id"dataTable"><thead><tr><th>序号</th><th>名称</th><th></th></tr></th…

Houdini 节点使用方法

Houdini 的节点系统是其程序化建模和特效制作的核心功能之一&#xff0c;通过节点网络实现程序化建模、特效制作、动力学模拟等复杂任务。掌握节点使用方法是高效创作的关键&#xff0c;以下是围绕用户需求的 全面、深入且结构化 的节点使用指南 一、节点基础操作 1. 创建与连…

license授权文件说明

license管理 1.使用场景 系统将自动检测license信息是否过期 - license过去前一个月&#xff0c;会显示warning&#xff1a;license file will expire in 30 days - 当license过去&#xff0c;会显示license file expired#注意 1. 数据库重启时才会启动 License 授权期限校验…

C++11中alignof和alignas的入门到精通指南

文章目录 一、引言二、内存对齐的概念和作用2.1 什么是内存对齐2.2 内存对齐的优势 三、alignof运算符3.1 定义和作用3.2 语法规则3.3 使用示例3.4 注意事项 四、alignas说明符4.1 定义和作用4.2 语法规则4.3 使用示例4.4 注意事项 五、alignof和alignas的结合使用六、实际应用…

防爆+高性能!ABB 防爆伺服电机HY系列守护安全生产

在石油、化工、火工等高风险行业中&#xff0c;如何在易燃易爆环境中确保设备安全稳定运行&#xff0c;同时兼顾高性能&#xff1f;ABB防爆伺服电机HY系列给出了完美答案&#xff01; 专为爆炸性环境设计&#xff0c;安全与性能兼得 ABB HY系列基于先进的HDS伺服平台打造&…

洪千武—华为海外HRBP

我的个人介绍 辰熙咨询创始人&CEO 2005年入职华为人力资源管理部 华为海外首批HRBP推动者、华为TUP股权激励实战顾问 华为IBM项目组成员、华为海外代表处AT成员 著有《OKR管理法则》、《力出一孔》 2005年以HR英文专才&#xff0c;从香港著名咨询公司被猎聘到华为人力…

测试:网络协议超级详解

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 </

游戏技能编辑器界面优化设计

界面布局重构 详细界面布局 ---------------------------------------------------------- | 顶部工具栏 [保存] [加载] [撤销] [重做] [测试] [设置] | --------------------------------------------------------- | 资源管理 | | 属性编…

【java中使用stream处理list数据提取其中的某个字段,并由List<String>转为List<Long>】

你当前的代码是这样的&#xff1a; List<String> gongkuangIds gongkuangBoundList.stream().filter(obj -> obj.getBoundValue() ! null).map(PlanSchemeProductionBoundInfo::getBoundValue).distinct().collect(Collectors.toList());这段代码从 gongkuangBoundL…

《前端面试题:JS数组去重》

JavaScript数组去重终极指南&#xff1a;从基础到高级的多种方法&#xff08;附面试题解析&#xff09; 在前端开发中&#xff0c;数组去重是JavaScript中最常见的需求之一。本文将全面解析8种数组去重方法&#xff0c;包括基础实现、ES6新特性、性能优化等&#xff0c;并附上…

基于51单片机的智能小车:按键调速、障碍跟踪、红外循迹与数码管显示(一个合格的单片机课设)

引言 在嵌入式系统领域&#xff0c;51单片机因其简单易用、成本低廉的特点&#xff0c;一直是入门学习的理想平台。今天我将分享一个基于51单片机的多功能智能小车项目&#xff0c;它集成了按键PWM调速、障碍物跟踪、红外循迹和数码管显示四大功能。这个项目不仅涵盖了嵌入式开…

Java异常处理(try-catch-finally):像医生一样处理程序的“感冒”

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、从一个真实问题开始&#xff1a;为什么需要异常处理&#xff1f; 假设你正在开发一个文件读取工具&#xff0c;用户输入文件名后&#xff0c;程序会读…

PostgreSQL 数据库故障与性能高效实时监测技术深度解析

关键词&#xff1a; postgresql 故障与性能监控 &#x1f4d1; 文章目录 1. 引言与监控重要性 2. PostgreSQL监控体系架构 3. 故障监控核心技术 4. 性能监控关键指标 5. 实时监测技术实现 6. 监控工具选型与部署 7. 故障预警与自动化响应 8. 性能调优监控策略 9. 最佳…