【Linux】线程
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
相关文章:

【Linux】线程
1.理解地址空间和页表 1.地址空间是进程能够看到的资源窗口 2.页表决定进程真正拥有的资源情况 3.合理的对地址空间和页表进行资源划分就可以对一个进程的所有资源进行划分:过地址空间分为栈区、堆区…通过页表映射到不同的物理内存。 在32位平台下,…...

ASP.NET Core MVC 从入门到精通之wwwroot和客户端库
随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生,…...

Oracle OCI 修改 Compute Instance Hostname
Oracle OCI 修改 Compute Instance Hostname Oracle Linux 7 及之后的版本 Oracle Linux 7 及之后的版本 1, Update the /etc/hostname file with below command. hostnamectl set-hostname <new name>2, Edit the oci configuration file for hostnames as given belo…...

垃圾收集算法面试总结
垃圾收集算法 标记 - 清除算法 首先标记出所有需要被回收的对象,标记完后统一回收所有被标记的对象。 后续的收集算法都是基于这种思路并对其不足进行改进而得到的。 这种方法主要有两个缺点: 一个是效率问题,标记和清除两个过程的效率都…...

grep替换指定字符串方法
在 Linux 命令行中,可以使用 grep 命令来查找匹配某个模式的字符串,并将其替换为另一个字符串。具体方法如下: grep -rl <pattern> <directory> | xargs sed -i s/<old_string>/<new_string>/g其中,<…...

主从模式、哨兵模式、集群模式(cluster)
主从模式、哨兵模式、集群模式(cluster) redis 实现高可用的方式分为 主从模式、哨兵模式、集群模式(cluster) 1. 主从模式(又称为主从复制) 表现为1个主节点,多个从节点,主节点负…...

题目3180:蓝桥杯2023年第十四届省赛真题-互质数的个数======及探讨互质专题
原题链接 https://www.dotcpp.com/oj/problem3162.html 想直接看题解的,跳转到第三次尝试即可。 已AC。 解析: (1)首先大家要知道什么叫互质: 以及它们的性质: 欧拉函数 在数论中,对正整…...

Java 文件操作
字符流-Writer和Reader用于读取文本-BufferedReader(new FileReader("path")) 读取文本文件-BufferedWriter(new FileWriter("path")) 写入到文本文件 字节流-InputStream和OutputStream图片、二进制文件-BufferedInputStream(new FileInputStream(new F…...

二叉树OJ题(C++实现)
文章目录 1.二叉树的层序遍历2. 二叉树的最近公共祖先3.二叉搜索树与双向链表4.从前序与中序遍历序列构造二叉树 1.二叉树的层序遍历 二叉树的层序遍历 OJ连接 主要思路是借助一个队列,将每一层的数据以size统计,当size为0时说明该层数据已经输入完&…...

grep -nr 命令查询字符串方式
grep -nr “搜索内容” 文件路径 其中: -n:显示行号-r:递归查找子目录中的文件“搜索内容”:要搜索的内容文件路径:要搜索的文件路径,可以是单个文件或目录路径(将会递归搜索该目录下的所有文…...

AgentAI+ChatGPT给出答案-为什么即时通讯需要心跳
序言 人工智能ChatGpt 结合系统化的问题拆解, 现在已经能够进行问题的拆解与自问自答, 预计未来很多的脑力工作要被释放了, 作为即时通讯的开发人员, 我问问专业的问题 为什么即时通讯需要心跳 先看产品界面与使用结果 问题拆解过程 执行任务1: 概念搜索 “Executing “Res…...

跨平台跨端的登录流程及其安全设计
跨平台跨端的登录流程及其安全设计 目录 跨平台跨端的登录流程及其安全设计 一、登录流程 1.1、登录流程时序图 1.2、三方App 登录 1.3、请求的路由守卫 二、注册流程 2.1、注册流程时序图 2.2、多因素认证 2.3、自动跳转登录页面 三、涉及的技术与安全 3.1、用户…...

如何在Java中创建临时文件?
在Java程序中,有时需要创建临时文件来暂存数据或者执行某些操作。Java提供了许多方式来创建临时文件。在本教程中,我们将介绍如何使用Java标准库来创建临时文件。 一、使用File.createTempFile()方法 Java标准库中的File类提供了createTempFile()方法来…...

Vue表单基本操作-收集表单数据
收集表单数据 使用vue中的v-model收集表单里面的数据,不同的表单元素配合v-model会有不同的写法和技巧 本次的表单元素包括:文本框,单选,多选,下拉框,文本域 编写表单元素 首先编写表单元素,…...

Android 一个获取网址时间的Demo
Android 一个获取网址时间的Demo 文章目录 Android 一个获取网址时间的Demo通过一个网址获取时间的代码关于Android NTP 时间Android 同步时间代码 前段时间有个客户想用局域网同步Android 设备的时间,开发后把这个demo分享一下。 效果: 这里也获取了阿…...

ijkplayer解码流程源码解读
ijkplayer是一款基于ffmpeg的在移动端比较流行的开源播放器。FFmpeg是一款用于多媒体处理、音视频编解码的自由软件工程,采用LGPL或GPL许可证。 要想理解ijkplayer源码,首先得知道视频播放器的基本原理。 视频播放器播放一个互联网上的视频文件…...

2023年值得关注的3个品牌趋势,帮你弯道超车
2023年,大环境开放,压抑三年的消费蓄势待发,品牌如何唤醒消费者的、热情成了重中之重的大事。 春风和煦,万物生长。又到了各类品牌、各位营销人踌躇满志、斗志昂扬的时候了,浅析一下2023品牌宣传趋势,抓住…...

软考-高级项目管理(二十)
第20章 高级项目管理 (P572考0-2分选择 性价比很低) 在项目集管理中涉及的相关角色主要包括: 项目集发起人、项目集指导委员会、项目集经理、其他影响项目集的干系人 1.项目集发起人 项目集发起人和收益人是负责承诺将组织的资源应用于项目集,并致力于使项目集取得…...

RTMP协议深度解析:从原理到实践,掌握实时流媒体传输技术
目录标题 1. 引言1.1 流媒体传输技术的重要性1.2 为什么选择RTMP协议1.3 RTMP协议的发展与应用 2. RTMP协议基础2.1 RTMP协议简介2.2 RTMP协议与其他流媒体协议的比较2.3 RTMP协议的组成与工作原理 3. RTMP协议详解3.1 RTMP数据单元(Message)3.2 RTMP数据…...

2023mathorcup数学建模ABCD思路分析
更多思路分析,请看文末 A题:量子计算机在信用评分卡组合优化中的应用 题目提到了信用评分卡的组合优化,这是一个经典的优化问题。在这个问题中,需要通过不同的组合方式来选择不同的阈值,以达到最大化贷款利息收入和最…...

普通家庭,千万不要投入大量时间和金钱,让孩子去苦学和培养AI机器人编程了...
普通家庭,千万不要投入大量时间和金钱,让孩子去苦学和培养一些看似高端,实际却用处不大的兴趣爱好课程了,比如学钢琴、学音乐、学AI机器人编程这些兴趣爱好课程。 这些对孩子的成长其实意义并不大,尤其是AI机器人编程。…...

C++学习(day2)
文章目录 四. C中的字符串4.1 C支持两种风格的字符串4.2 string类型的赋值和初始化4.3 C风格和C风格的字符串互换4.4 string类中三个重要成员函数4.5 string类型的比较4.6 string类型的成员访问 at()6.8 string类型数据的输入 五、bool类型六、引用(reference&#…...

软考 - IP地址与网络划分
一.IP组成 1.1 首个八位字节规则 1.2 地址掩码 IP地址掩码 标准地址掩码 A类:255.0.0.0 前1个字节是网络号 后3个字节是主机号 B类:255.255.0.0 前2个字节是网络号 后2个字节是主机号 C类;255.255.255.0 前3个字节是网络号 后1个字节是主机号…...

Apifox软件的基础使用方式
Apifox软件的基础使用方式 简单方便的用途 该工具是接口在线调试工具,这里我给到连接供大家去官网下载,我个人觉得是比较于postman工具好用,提供的语言操作是中文版本的便于操作 下载和安装 https://apifox.com/?utm_sourcebaidu&ut…...

【Tensorflow】模型如何加载HDF文件数据集?
如果每个样本都被保存为一个单独的 HDF5 文件,可以使用 tf.data.Dataset.list_files 函数来创建一个文件名数据集,然后使用 tf.data.Dataset.interleave 函数来并行读取多个文件。 下面的示例展示了如何从多个 HDF5 文件中读取数据并创建一个 tf.data.D…...

校招又临近了,怎么在面试中应对设计模式相关问题呢?
夏天开始了,那么夏天结束时的毕业季也不远了。毕业是个伤感、期待而又略带残酷的时节,就像蜜桃无论成熟与否都会在这个时间被采摘,如果毫无准备就踏入社会,就会……马上变成低级社畜。所以说还是要早点为了毕业找工作做点准备&…...

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

神经网络的理解
文章目录 概念得分函数损失函数神经网络结构非线性激活函数神经网络运行过程神经网络能够做的事情概念 人工神经网络(Artificial Neural Networks,简写为ANNs)也简称为神经网络(NNs)或称作连接模型(Connection Model),它是一种模仿动物神经网络行为特征,进行分布式并…...

夏驰和徐策带你从零开始学数据结构——哈希表
哈希表的概念: 哈希表是一种常用的数据结构,它可以在 O(1) 的时间复杂度内执行插入、查找和删除操作。哈希表的核心思想是使用哈希函数将键值对映射到数组中的一个位置上,从而实现快速的访问和修改。 哈希表由两个主要部分组成:…...

linux实现网络程序
1️⃣ 在linux下,通过套接字实现服务器和客户端的通信。 2️⃣ 实现单线程、多线程通信。或者实现线程池来通信。 3️⃣ 优化通信,增加守护进程。 有情提醒,类里面默认的函数是内联。内联函数在调用的地方展开,没有函数地址&…...