【Linux内核系列】:进程板块与文件板块的综合

🔥 本文专栏:Linux
🌸作者主页:努力努力再努力wz

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

💪 今日博客励志语录人生中成功只是一时的,失败却是人生的主旋律,但是如何面对失败却把人分成了不同的样子,有的人会被失败击垮,有的人会爬起来继续向前,所以你会选择成为什么样的人呢?

那么在此前的一系列的文章,我主要围绕展开讲解了Linux的进程板块与文件系统板块,学习完了这两个板块的知识点之后,那么这两个板块的内容其实并不是独立隔离开的而是有联系的,那么有了文件系统板块的知识点之后,其实我们进程板块的很多知识点就可以在进一步的完善,那么本篇文章的核心就是关联其我们进程板块与我们的文件板块,那么废话不多说,就进入正文的学习

★★★ 本文前置知识:

文件系统收尾

文件系统

缓冲区

进程的替换

进程地址空间


引入:内存管理

想必进程的创建想必大家一定非常熟悉,那么在进程创建之前,我们需要将该进程对应的可执行文件给加载到内存中,那么我们知道内存和外部设备磁盘一样,是一个物理结构,那么必然也要经过操作系统的管理,那么操作系统管理一个事物的方式是首先得为该事物建立一个逻辑映射来描述该事物,比如磁盘,那么操作系统便用一个一维的线性数组来描述磁盘这个物理结构,那么其中该一维的线性数组的每一个元素便是扇区,同理操作系统要描述内存,必然也得为内存建立一个逻辑结构

那么我们知道CPU在运行进程的代码的时候,那么会从内存中获取该进程的相关数据,而CPU要获取该进程的相关数据,必然得告诉内存目标数据在内存中的物理位置,从而内存能够定位到该数据然后交给CPU,而CPU与内存之间通过地址线相连,那么以32为机器为例,那么CPU与内存的地址线就是32根,那么每一根地址线的高低电频信号用来表示二进制的0和1,那么内存就能够获取到这32根地址线组合得到一个二进制序列,那么该二进制序列便是地址,那么32根地址线总共就能够表示出2的32次方个不停的地址,也就是从0000 0000到FFFF FFFF连续的大小为4GB的地址空间,那么该地址空间就可以用一个一维的数组来表示,其中该数组的每一个元素就是一个逻辑地址,那么每一个进程都有各自的独立的一份虚拟地址空间,那么该虚拟地址空间就是内存的一个逻辑映射

那么这些地址是逻辑上的地址,就如同我们磁盘上一维线性数组中的逻辑块的LAB地址一样,那么他们就需要经过转化映射得到实际的物理内存地址,所以便有了页表这个数据结构,那么其中页表就记录的是虚拟地址到内存的物理地址的一个映射,那么CPU拿着虚拟地址经过其MMU也就是CPU的内存管理单元,然后MMU通过页表就能实现虚拟地址到物理地址的一个转化,从而交给内存定位到目标数据
在这里插入图片描述

而对于物理内存来说,我们操作系统将连续的物理内存空间其中按照4KB的数据为一个集合来划分,其中这每一个集合就是一个页框,那么为了管理整个物理内存就转换为了管理这划分的一个一个的页框,那么管理的方式就是我们最为熟悉的先描述,再组织了,也就是说操作系统会为每一个页框定义一个page结构体,那么该结构体存储了该页框的各种属性,其中最关键的便是一个整形的flag作为标志位,那么该整形flag变量的每一个二进制位都有特定的含义,那么其中就包括了该页框是否被使用等,那么其中page结构体还包括一个变量count也就是引用计数,记录该页框被多少进程所共享,那么在进程的视角下,物理内存是4GB,而页框的大小是4KB,那么也就是说总共大概会有1048576个页框

  struct page {unsigned long flags;        // 标志位(如PG_locked、PG_dirty)atomic_t _count;            // 引用计数(共享次数)atomic_t _mapcount;         // 页表映射计数struct address_space *mapping;  // 关联的地址空间(文件映射时使用)pgoff_t index;              // 页框在文件或内存中的偏移struct list_head lru;       // LRU链表(用于页面置换算法)// 其他字段(如内核slab分配器相关)};

那么为了管理这么多的页框,那么操作系统的内核中会维护一个全局的变量mem_map本质上也就是一个struct page数组,那么该数组的每一个元素就对应一个page实例,那么我们可以通过内存的逻辑地址也就是地址空间的虚拟地址来根据其页表来映射转换得到内存的物理地址,而虚拟地址的二进制序列是由页目录索引、页表索引、页内偏移所构成。

以虚拟地址 0x08048000为例: 0x08048000 → 分解为:页目录索引(0x20)、页表索引(0x48)、页内偏移(0x000)。

然后MMU通过页目录索引以及页表索引在页表中逐级查找得到页框号PFN再结合页内偏移最后在将两者转化得到物理内存地址

而物理地址的前12位便是该物理地址所对应的页框的page结构体在mem_map的一个偏移量也就是PFN,那么我们就可以根据偏移量来定位到其对应的page结构体,这样就完成了一个虚拟地址到物理地址再到对应的page结构体的一个映射

虚拟地址空间 (进程视角)

└── 页表 (Page Table)

└── 物理地址 (硬件层)

└── 物理页框 (4KB)

└── struct page (元数据)

└── mem_map[PFN] (全局管理)

而我们发现如果是对于EXT4文件系统来说,那么该文件系统下的逻辑块的大小是4KB,而页框的大小也为4kb,那么必然我们的内存与磁盘的逻辑块就能够达成一个1:1的映射关系,那么至于映射规则以及过程是什么的,那么又是说来话长,本文肯定是讲不完的,所以便不再阐述了,读者感兴趣可以下去自己了解

完善进程的创建的全过程

那么我们现在我们要结合我们之前所学的进程板块与文件板块来完善进程创建的一个完整的过程的话,那么这个过程的起点就应该从系统调用说起,

我们知道了我们在Linux上创建的各种进程,本质上都是我们命令行解释器也就是shell外壳程序的子进程,那么shell外壳程序会调用fork系统调用接口来创建一个子进程,那么此时就会复制拷贝一份父进程的task_struct结构体然后修改其中部分属性比如PID以及PPID等得到子进程自己独立的一份task_struct结构体,至于数据层面上,那么子进程是共享父进程的物理内存页面的,但是为了进程的独立性,操作系统会采取了写时拷贝机制,也就是一旦进程对共享的数据进行写入操作的时候,那么便会触发写时拷贝机制,那么此时操作系统会为写入的数据在内存中为其开辟一份副本从而做到父子进程的数据的独立,那么fork调用结束后,下一个环节便是进程的替换,那么此时会调用exec族函数,那么它会获取到替换的目标进程的对应的可执行文件的文件名以及路径,那么没错,现在这部分过程就开始与文件板块串联起来了,获取文件名以及路径是目的是要从该文件所处的目录文件中的目录项中获取对应的文件名和其inode编号的映射关系从而获取该可执行文件的inode编号,那么有了该文件的inode编号之后,那么便可以转化为磁盘中的物理内存地址从而进行定位,而inode块中有其关联的保存文件内容的数据块的索引,那么意味着此时我们便能同时定位到该可执行文件的inode块以及对应的数据块,从而将其加载到内存中,然后接着又切换到我们的进程板块
在这里插入图片描述
一旦该进程对应的可执行文件加载到内存中之后,那么那么进程的替换不会为替换的新的进程创建一个task_struct结构体,而是修改该进程的页表也就是映射关系,从而将该子进程的上下文替换为目标进程的上下文,那么子进程运行结束退出后接着父进程会利用waitpid接口获取子进程的退出情况也就是退出码,那么这就是结合了文件板块之后,我们完善我们对于进程的创建的全过程的一个理解

完善用户缓冲区写入

那么我们有了文件系统以及进程的概念之后,我们便能够理解以及完善用户缓冲区写入的一个全过程

那么我们知道当我们调用c语言提供的fwrite库函数向目标文件做写入时,那么写入的数据不会直接到内核中而是先保存在c语言提供的一个用户层面上的缓冲区,然后再根据特定的刷新策略比如行缓冲或者全缓冲调用write接口刷新到内核中去

而我们向目标文件写入的数据前提肯定是该目标文件被打开了,那么既然该文件被打开,那么必然要调用fopen函数或者open接口,那么open系统接口会获取该打开的目标文件的文件名以及所处路径,然后会根据该路径解析得到该目标文件所处的目录,然后扫描其目录项得到映射关系从而获取该文件的inode编号从而定位到磁盘中的相应位置将该文件的inode块以及其关联的数据块加载到内存当中,并且为其创建一个内核层面上的file结构体,以及定义一个inode结构体保存inode块的数据,那么file结构体内部就有inode结构体的间接引用,而进程内部会有一个指针数组记录其打开的文件,那么每一个元素指向一个该进程打开的文件的file结构体,那么创建完file结构体之后,就会从数组开始线性扫描该指针数组寻找空余位置然后指向该file结构体并返回该数组位置的下标

那么此时有了数组下标之后,我们便能获取该文件的file结构体,那么其中file结构体中有一个address space字段,其中保存了一个指向基数树的数据结构的指针,那么我们该打开的文件一定保存在特定位置的内存的页框中,所以得通过基数树来寻找定位到其page结构体然后写入到页缓存中去,最后再由操作系统刷新到磁盘中去,这也就是为什么要有用户缓冲区的意义,因为每次写入页缓冲,那么其在基数树的定位都需要时间开销
在这里插入图片描述

结语

那么这就是本篇文章的全部内容,那么大家在学习Linux的各个板块的时候,比如进程与文件系统,它们之间不是独立没有联系的,而是可以结合这两个板块的知识,去完善我们很多过程,加深这两个板块之间的理解,这就是本文想要传达的,那么我的下一篇文章是动静态库,那么我会持续更新,希望你能多多关注,如果本文有帮组到你的话,还请多多三连加关注哦,你的支持就是我创作的最大动力!
在这里插入图片描述

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

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

相关文章

CellOracle|基因扰动研究基因功能|基因调控网络+虚拟干预

在gzh“生信小鹏”同步文章 论文来源: 发表期刊:Nature发表时间:2023年2月23日论文题目:Dissecting cell identity via network inference and in silico gene perturbation研究团队:Kenji Kamimoto 等,华盛顿大学医学院1. 研究背景与问题提出 细胞身份(Cell Identit…

专线、云 和 物联网(IoT)

专线、云 和 物联网(IoT) 是现代信息与通信技术(ICT)领域的三大重要组成部分,它们在企业和个人的数字化转型中扮演着关键角色。以下是对这三者的详细介绍及其相互关系: 1. 专线(Leased Line&…

[Lc14_priority_queue] 最后一块石头重量 | 数据流中的第 K 大元素 | 前K个高频单词 | 数据流的中位数

目录 1.最后一块石头的重量 题解 2.数据流中的第 K 大元素 题解 3.前K个高频单词 题解 代码 ⭕4.数据流的中位数 题解 在C中,使用标准库中的priority_queue,默认情况下它是一个最大堆(即大堆排序),这意味着最…

XSS漏洞靶场---(复现)

XSS漏洞靶场—(复现) 反射型 XSS 的特点是攻击者诱导用户点击包含恶意脚本的 URL,服务器接收到请求后将恶意脚本反射回响应页面,浏览器执行该脚本从而造成攻击,恶意脚本不会在服务器端存储。 Level 1(反射型XSS) 此漏…

2025/3.17 郭院安排会议与南京银行参访

目录 *郭院会议:服务外包*1.会遇到的问题以及解决方案2.考虑行业目前会碰到的瓶颈3.后端应该呈现处理图像的过程4.记得做报告、文档说明和视频等工作 *南京银行(鑫合易家)参访记录*1. 风险评分业务流程笔记![在这里插入图片描述](https://i-b…

Cloud Ace 宣布成为 Langfuse 亚太地区首个代理商,提供 LLM 全链路解决方案

Cloud Ace 宣布正式代理 Langfuse 产品,是 Langfuse 在亚太地区唯一的官方授权经销商,全面负责其商用许可证的销售、部署与技术支持服务。通过此次合作,Cloud Ace 将充分发挥 Langfuse 的先进技术能力与行业专业知识,为企业级客户…

Helm 的仓库管理与 Chart 搜索

在使用 Helm 管理 Kubernetes 应用的过程中,仓库管理与 Chart 搜索是两个核心功能。通过 Helm 仓库,用户可以方便地存储、分享和获取 Helm Chart,而搜索功能则帮助用户快速找到所需的 Chart。本文将详细介绍 Helm 仓库的概念、管理方法以及如…

Matlab 汽车振动多自由度非线性悬挂系统和参数研究

1、内容简介 略 Matlab 169-汽车振动多自由度非线性悬挂系统和参数研究 可以交流、咨询、答疑 2、内容说明 略 第二章 汽车模型建立 2.1 汽车悬架系统概述 2.1.1 悬架系统的结构和功能 2.1.2 悬架分类 2.2 四分之一车辆模型 对于车辆动力学,一般都是研究其悬…

免训练指标(Zero-Cost Proxies)

1. 什么是免训练指标(Zero-Cost Proxies,ZC proxies)? 免训练指标是一类 无需完整训练模型即可评估其性能的度量方法,主要用于提高 神经架构搜索(NAS) 的效率。 传统 NAS 需要训练候选架构来评…

C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷二)

目录 1. 数组名与地址 2. 指针访问数组 3.一维数组传参本质 4.二级指针 5. 指针数组 6. 指针数组模拟二维数组 1. 数组名与地址 我们先看下面这个代码: int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int* p &arr[0]; 这里我们使用 &arr[0] 的方式拿到了数…

基于Python pyscard库采集ACS ACR122U NFC读卡器数据的详细操作步骤

步骤1:安装驱动 1. 下载驱动: - 访问ACS官网的驱动下载页面:[ACR122U驱动下载](https://www.acs.com.hk/en/drivers/6/acr122u-nfc-reader/)。 - 选择适用于Windows的驱动(如 ACR122U Driver (Windows) V3.05.02.zip)…

深度学习 Deep Learning 第1章 深度学习简介

第1章 深度学习简介 概述 本章介绍人工智能(AI)和深度学习领域,讨论其历史发展、关键概念和应用。解释深度学习如何从早期的AI和机器学习方法演变而来,以及如何有效解决之前方法无法应对的挑战。 关键概念 1. 人工智能的演变 …

python实现简单的图片去水印工具

python实现简单的图片去水印工具 使用说明: 点击"打开图片"选择需要处理的图片 在图片上拖拽鼠标选择水印区域(红色矩形框) 点击"去除水印"执行处理 点击"保存结果"保存处理后的图片 运行效果 先简要说明…

软件功能性测试有哪些步骤和挑战?软件测评服务机构分享

软件功能性测试是对软件系统进行验证的一种基本方法。其主要目标是确保软件系统能够按照预期的要求和功能进行操作。从用户的角度看,功能性测试旨在检查软件是否实现了所有要求的功能,保证用户体验的顺畅与满意。 一、软件功能性测试的测试步骤   1、…

《C#上位机开发从门外到门内》3-4:基于TCP/IP的远程监控系统设计与实现

文章目录 一、项目概述二、系统架构设计三、通信协议设计四、功能模块实现五、系统安全性与稳定性六、性能优化与测试七、实际应用案例八、结论 随着信息技术的飞速发展,远程监控系统在工业自动化、智能家居、环境监测等领域的应用日益广泛。基于TCP/IP协议的远程监…

在react当中利用IntersectionObserve实现下拉加载数据

目录 一、传统的下拉加载方案 二、存在问题 1.性能较差 2.不够精确 三、IntersectionObserve版本下拉加载 1、callback 2、options 四、IntersectionObserver实例 1、Intersection的优势 2、实现思路 3、代码实现 在进行前端开发的过程中,常常会碰到下拉…

深入理解C++编程:从内存管理到多态与算法实现

C 是一门功能强大的编程语言,广泛应用于系统编程、游戏开发和高性能计算等领域。本文将通过一系列经典问题,深入探讨 C 的核心知识点,包括内存管理、多态(结合函数重载与覆盖)、多线程、TCP/IP 模型、软链接与硬链接的…

相对论之光速

然而,基础物理学的进步很少全部由实验取得。为了解实验结果背后的机制,法拉第问道,既然磁铁没有接触导线,导线中怎么会产生电流?一股电流又怎么能使指南针指针发生偏转?有某种作用因素必然在磁铁、导线和指南针之间的空隙中传递…

文本检测-文本内容审核-文本过滤接口如何用PHP调用?

一、什么是文本检测接口呢? 文本内容审核过滤,提供对敏感事件、违规词语及监管要求封禁词语的识别审核能力,包含海量历史数据,有效过滤违禁违规、恶意推广、低俗辱骂、低质灌水、广告法审核,该接口应用场景广泛&#…

突破极限:猎板PCB在HDI盲埋孔树脂塞孔工艺中的创新与挑战

在高端电子制造领域,HDI(高密度互连)技术凭借其高精度、高可靠性的特点,已成为5G通信、航空航天、智能汽车等领域的核心技术支撑。作为HDI板制造的核心环节,盲埋孔树脂塞孔工艺直接决定了电路板的信号完整性、散热性能…