当前位置: 首页 > news >正文

24.线程概念和控制(一)

一、Linux线程概念

1.概念角度,感性地理解线程

从教材角度:

进程 = 内核数据结构 + 代码和数据(执行流)

线程:进程内部的一个执行分支(执行流)

内核和资源:

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

线程:CPU调度的基本单位

进程模拟线程:

        进程访问的大部分数据都是通过进程地址空间访问的!-> 进程地址空间就是窗口,创建一个进程,把窗口共享,分配给多个task_struct,划分地址空间和虚拟地址范围 -> 那么就模拟出线程了(线程是进程内部的一个执行分支)

不同视角下的线程:

Linux操作系统视角:执行流

CPU视角:轻量级进程

初步理解:

结论1:Linux线程可以用进程来模拟

结论2:对资源的划分,本质就是对进程虚拟地址范围划分。虚拟地址,就是资源的代表。

结论3:代码区划分?函数就是虚拟地址(逻辑地址)空间的集合!就是让线程未来执行ELF程序的不同部分即可。

结论4:原理解的进程是进程的一种特殊情况,只有一个task_struct,一般情况有多个。

结论5:Linux的线程,就是轻量级进程或者用轻量级进程模拟实现的。

             操作系统学科只提供概念,具体的操作系统提供设计思路和设计方案。

问题1:为什么要这样设计?

复用代码,用轻量级进程来模拟线程,使得兼容性和代码的可维护性比较好。以及调度算法和管理都能沿用,不需要重新设计。

问题2:其他平台,比如windows也是这样设计的吗?

windows给线程设计了单独的结构TCB。

线程和进程的理解和区别:

进程强调独立性,部分共享(进程间通信)

线程强调共享,部分独占

具体例子理解:

        家庭是分配社会资源的基本载体,而家庭内有很多成员,成员有各自的目标和资源,家庭内有公共的资源。(家庭->进程,成员->线程)

2.从理性角度,资源划分(虚拟到物理,页表,页表相关概念,部分内存管理的理解)

物理内存在是连续不断的,并没有内存块的概念。(内存块是操作系统的概念)

OS访问磁盘是以块为单位来访问,大小为4KB。可执行程序就是文件,在磁盘中存储。可执行程序,存储的时候,天然就是4KB单位存储的,无论属性还是内容。

理解:4GB/4KB=1,048,576

4KB划分,是操作系统划分的,不管是磁盘(文件系统)还是内存。OS要不要管理页框?

先描述,在组织。

先有struct page结构,再用struct page mem[1048576]; 数组管理。

如何得知具体的page对应内存块的物理地址?(注:内存块不等于page)

        每一个page都有下标 -> 假设第一个page对应的内存块起始物理地址从0开始,每一个page对应内存块起始物理地址就知道了(index*4KB)-> 具体内存块物理地址 = 内存块起始物理地址 + 页内(4KB)偏移 -> 因此不需要在page内保存其对应内存块的物理地址

        文件结构struct file中有adress_space,里面有radix_tree,管理的是page,因此文件可以通过拿到page的物理地址,从而计算出下标,拿到page对应的内存块的物理地址。

        申请物理内存,本质就是在:1.查数据,改page   2.建立内核数据结构的对应关系。

page结构中几个比较重要的参数:

        flags :用来存放页的状态。这些状态包括页是不是脏的,是不是被锁定在内存中等。flag的每一位单独表示一种状态,所以它至少可以同时表示出32种不同的状态。这些标志定义在<linux/page-flags.h>中。

        _mapcount :表示在页表中有多少项指向概页,也就是这一页被引用了多少次。当计数值变为-1时,就说明当前内核并没有引用这一页,于是在新的分配中就可以使用它。

        virtual :是页的虚拟地址。通常情况下,它就是页在虚拟内存中的地址。有些内存(即所谓的高端内存)并不永久地映射到内核地址空间上。在这种情况下,这个域的值为NULL,表示该物理页没有固定的内核虚拟地址,需要的时候,必须动态地映射这些页。

拓展高端内存:

        32位系统的地址空间限制:在32位系统中,理论地址空间为4GB。Linux默认将内核空间划分为高1GB(如0xC0000000~0xFFFFFFFF),用户空间为低3GB。若物理内存超过内核直接映射区(Direct Mapping Area,通常3GB~3GB+896MB),剩余物理内存(即“高端内存”,约超过896MB的部分)无法被内核空间永久映射。

页表

以32位操作系统举例,虚拟地址是4个字节,32比特位。

从高位到低位,第一组:高10位,第二组:次高10位,第三组:最后12位

取值范围分别是[0,1023],[0,1023],[0,4095]。

页表分为两级:

第一级:页目录,页目录存放的是页表的地址,一共1024个

第二级:页表,页表存放的是物理页的地址,一共1024个

为什么要分级设计?

        如果不分级设计,一个页表若要映射4GB空间,4GB/4KB=1,048,576,32位地址大小是4字节,1048576*4B=4MB,页表大小就是4MB。而且页表自身不能做到内存块的分离,页表自身需要的内存页就必须是连续的,总共要4MB/4KB=1024个内存页。页表设计初衷就是为了实现虚拟地址对应的物理页是离散分布的,自身就违背了。此外,根据局部性原理可知,很多时候进程在一段时间内只需要访问某几个页就可以正常运行了。因此也没有必要⼀次让所有的物理页都常驻内存。

结论:

细节1:申请内存->查找数组->找到没有被使用的page->page index->物理页框地址

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

细节3:进程,一张页目录+n张页表构建的映射体系虚拟地址是索引,物理页框地址是目标,物理地址 = 虚拟地址低12位(页内偏移) + 页框地址 。

细节4:为什么是低12位数字?ELF格式编址,页框大小都是4KB。

        页目录的物理地址被 CR3 寄存器指向,这个寄存器中,保存了当前正在执行任务的页目录地址。
虚拟地址到物理地址转化有CPU内MMU自动完成。

3.线程深刻理解

执行流看到的资源本质:在合法的情况下,你有多少虚拟地址(虚拟地址是资源的代表

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

页表是一张从虚拟到物理的地图。

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

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

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

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


文章转载自:

http://664FRbec.ppbqz.cn
http://gtwONDjU.ppbqz.cn
http://oZKmRaH1.ppbqz.cn
http://KVduKfq3.ppbqz.cn
http://yVtrC7MG.ppbqz.cn
http://GaCJJnNJ.ppbqz.cn
http://2ybM9fcM.ppbqz.cn
http://xS2FOwjK.ppbqz.cn
http://imfq2iBl.ppbqz.cn
http://3M3xQQbG.ppbqz.cn
http://WorlwrKP.ppbqz.cn
http://og2flNNS.ppbqz.cn
http://UXZ0PUoL.ppbqz.cn
http://l3uAy9CJ.ppbqz.cn
http://N0EYXy5U.ppbqz.cn
http://F8Ak2DcV.ppbqz.cn
http://32uS85Ew.ppbqz.cn
http://ORSShKwJ.ppbqz.cn
http://v8Dye1KJ.ppbqz.cn
http://yMlm8m6s.ppbqz.cn
http://8hXiCnsX.ppbqz.cn
http://4xSNcymJ.ppbqz.cn
http://0qeY6PNK.ppbqz.cn
http://WyUDpJbJ.ppbqz.cn
http://0ee2z0Jo.ppbqz.cn
http://K5hJkOPq.ppbqz.cn
http://zU9sHQ7f.ppbqz.cn
http://RFgASPlm.ppbqz.cn
http://1FY8xNT3.ppbqz.cn
http://dVao9PWj.ppbqz.cn
http://www.dtcms.com/a/369823.html

相关文章:

  • Altium Designer(AD24)切换工作界面为浅灰色的方法
  • 让字符串变成回文串的最少插入次数-二维dp
  • 零基础入门深度学习:从理论到实战,GitHub+开源资源全指南(2025最新版)
  • 从文本到知识:使用LLM图转换器构建知识图谱的详细指南
  • 【开题答辩全过程】以 停车场管理系统的设计与实现为例,包含答辩的问题和答案
  • 带fat32文件系统的bin二进制文件制作教程
  • 【Redis】缓存的穿透、击穿和雪崩
  • C++经典的数据结构与算法之经典算法思想:分治法(Divide and Conquer)
  • PDF教程|如何把想要的网页保存下来?
  • DevOps实战(2) - 使用Arbess+GitPuk+Docker实现Java项目自动化部署
  • Git reset 回退版本
  • PostgreSQL与Greenplum数据库的编程语言连接
  • git在Linux中的使用
  • 全面剖析TENGJUN防水TYPE-C板上双排贴(L7.55/舌片外露1.1/双耳带螺孔):认证、防水与结构设计的三重突破
  • fastapi通过sqlmodel连接Mysql实现crud功能
  • 百度竞价推广:搜索竞价信息流推广代运营
  • Go基础(④指针)
  • 【开题答辩全过程】以 基于JSP的高校健康体育活动管理系统的设计与实现为例,包含答辩的问题和答案
  • 贪心算法应用:基因编辑靶点选择问题详解
  • webrtc弱网-LossBasedBandwidthEstimation类源码分析与算法原理
  • 01-线上问题处理-树形结构拼接
  • uniapp | 解决组件样式不生效问题
  • 尚硅谷宋红康JVM全套教程(详解java虚拟机)
  • uniapp基础组件概述
  • C++和OpenGL实现3D游戏编程【连载30】——文字的多行显示
  • 使用UniApp实现下拉框和表格组件页面
  • 人工智能学习:基于seq2seq模型架构实现翻译
  • Day12--HOT100--23. 合并 K 个升序链表,146. LRU 缓存,94. 二叉树的中序遍历
  • Hive on Tez/Spark 执行引擎对比与优化
  • 03.缓存池