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

合作网站账号登录方式网页设计100种技巧

合作网站账号登录方式,网页设计100种技巧,做平面素材好的网站,react.js 做网站好吗前言 首先#xff0c;我们先要对 内存当中存储 各个数据之间的 结构要有一个 大概的了解#xff1a; 各个区当中存储的数据使用类型不同#xff0c;所以#xff0c;这些数据在使用方式上是有差别的。比如下面这个例子#xff1a; 在C 语言当中我们不能直接对 上述的 str…前言 首先我们先要对 内存当中存储 各个数据之间的  结构要有一个 大概的了解 各个区当中存储的数据使用类型不同所以这些数据在使用方式上是有差别的。比如下面这个例子 在C 语言当中我们不能直接对 上述的 str 这个字符指针直接进行解引用修改因为此时这个 str 指向的是 hello Linux! 这个字符串的手字符地址管理的是这个 常量字符串而常量字符串是存储在 字符常量区当中的在这个 字符常量区当中的 数据在初始化创建之后是不能再进行修改的。 所以上述的 *str H 这句代码的意思就是把 hello Linux! 这个字符串当中的首字符修改成 H 这个字符这肯定是不行的所以会报错。 那么在上面描述 什么 字符常量区栈区堆区等等的这些区的图当中这些区的整合这整个是在内存当中存储的吗 了解这个问题之前我们先来了解一下在 C 当中的各种变量在 这些区当中是如何去存储的 利用下述的代码打印出来的地址位置来验证上述的是否是正确 的   打印 对应的 区空间如下图所示   我们发现其中的地址大小其实是按照上述的图来划分存储的如果你仔细观察可以发现其中的 地址是按照 从下往上地址是 逐渐增长的。 而在 栈区和 堆区当中中间有一块空着的空间这块空间其实是有点大的而两个区 的 数据是对向生长的 我们可以验证如下所示是在栈区当中存储的 局部变量的地址可以发现是越在后创建的变量地址越小 输出 你可以发现我们是按照开始对 局部变量的定义顺序来 打印的 地址你可以发现这个地址是从上往下依次递减的。所以我们就证明了 在栈区当中的 数据是往低地址方向来开辟空空间的。 所以按照栈这个数据结构的存储数据的方式先来的 数据先入栈是在栈底位置的而 后来的数据 后入栈就是往 栈顶方向来开辟空间的当然就是 后来的数据地址小啊。  同样的还可以证明堆区当中存储    输出   你可以发现我们打印 堆上开辟空间这些空间的起始地址是按照定义顺序来打印的 而打印的地址的是按照从上往下地址一次增大 。至此也就证明了在堆当中的空间是往高地址来开辟空间的 。  所以我们才会说堆 和 栈之间是有一大片空间的而 堆 和 栈是开辟空间的方向是 对向的。 那么为什么要这样做呢其实这样可以方式 栈 和 堆开辟空间过多而占用到 过多的内存资源栈 和 堆能开辟的最多空间资源就是 堆 和栈 之间的 那一段 空间。而通过上述对 堆 和 栈区的首地址打印我们发现其实这段空间之间的差距看上去还是蛮大的 因为上述使用的系统是 64 位的所以差别就更大了。同样就算是 X86 的机器差别也很大。 首先我们知道全局变量是一直存在的全局变量的声明周期是整个程序。不会随着程序当中的某一函数的返回而释放。 我们把 已初始化的全局变量区 和 未初始化的全局变量区这个两个区称为 全局数据区。只要是这个程序的地址空间存在那么这个 全局数据区当中的数据就会释放。 这里也就衍生出一个语法当我们在某一个函数当中 定义一个 static 的变量的时候这个 static的变量不会随着 这个函数的 返回而释放这个 static 变量的 声明周期是整个程序。但是 static 变量在初始化之后就不能在修改了。 那么static 变量是如何做到上述本函数释放但是 static 变量不会释放的呢 其实是因为 static 变量在编译之时已经被编译到全局数据区了。 也就是说static 本身已经是一个 全局变量了但是static 变量是在函数体当中定义的所以static 变量被迫只能在 本函数体当中被使用。也就是说static变量的 作用域 是在本函数当中但是 static的声明周期 是在 全局的。 通过上述对于 全局变量的描述相信你对全局的 概念有了一些了解现在我们看看下面这个例子我们使用 fork函数来 创建出一个子进程然后在子进程循环 和 父进程循环当中打印出 同一个 全局变量的 值 和 地址   我们把 g_value 这个全局变量的 值 和 地址在父进程和子进程当中的值都打出来 发现 子父进程 g_value 的值和 地址都是一样的这个我们先不看当我们在子进程当中把 g_value 的值修改了但是在 父进程当中不进行修改那么会影响到父进程吗 如上所示我们对子进程的代码做如上处理父进程代码不做处理当在子进程当中修改到 g_value 的时候打印结果如下   如上所示子进程的 g-value 修改到了 200但是 父进程却还是0 。其实这个还不是最怪的因为 进程之间是要独立的。在子进程修改其中的变量之前父子进程读取的是一个变量但是如果子进程对某一个变量进行了修改那么就会发生写时拷贝只是多拷贝一个 相同的变量地址空间给 子进程自己用此时相当于是 父子进程使用的是同名的两个变量。 但是奇怪的是上述子父进程打印的 g_value 变量的地址是一样的啊但是访问出的值却是不一样的。他是怎么做到的呢 所以如果上述的地址是一个物理地址那么是绝对不可能出现上述的情况的。所以这个地址绝对不是一个物理地址。要不然如果是一个物理地址的话两个进程读取同一块空间的数据读取的数据会不一样呢 其实这个地址是  线性地址虚拟地址。 我们在 C/C 当中使用的地址其实都不是物理地址他只是一个映射在 物理地址 的 线性地址。 进程地址空间 父进程和子进程之间在虚拟地址和物理地址之间的映射关系 现在我们把前言 当中所说的 这个结构称之为 进程地址空间。 你可能对上述的结构比较熟悉可能知道他是C/C 的 内存当中排布。实际上这个是有 更官方的 名字叫做 进程地址空间的。 既然叫做进程地址空间说明这个空间应该是属于一个进程的在 Linux 当中管理一个 进程是通过 管理 操作系统给 这个进程创建的 PCB 对象来管理的所以进程的 进程地址空间 的 起始地址是存储在 PCB 当中的。方便操作系统 通过 PCB 来查找到 这个进程地址空间。 而在 C/C 当中我们使用的指针我们看到的都是 上述从 0000.....0000 到 FFFF.....FFFF 这个地址其实这个地址只是一个虚拟地址这个地址是映射在内存当中的。 具体如何映射其实在内存当中吗存储的有 页表这个 数据结构这个页表是 K-V 的方式来存储数据的。 而 K-V 代表的就是 虚拟地址 和 物理地址的映射关系比如在 全局数据区当中创建了一个 全局变量那么这个变量我们如果取地址的话看到是这个变量的虚拟地址这个虚拟地址在页表当中存储着同时这个虚拟地址映射着一个物理地址这个物理地址就是实际在内存当中存储这个 变量的数据所在空间。 同样的如使用 父进程来创建出一个子进程的话操作系统同样会帮这个子进程来创建出属于 子进程 自己的 PCB 结构体而且其中的数据如果是和父进程 共有的都是按照 父进程当中变量数据当做模版来创建的如果是子进程私有的那么就会进行初始化。 在子进程被创建出来之后每一个进程都需要有一个 进程地址空间被创建出的 子进程 也不例外。所以子进程也要拷贝一份 地址空间给自己。同时页表也要拷贝一份或者是使用同一张页表但是子进程也是有自己的独立的数据的所以还是需要自己的 页表。 这里应该就理解了 为什么子进程和 父进程共享一个 代码因为 就算是是两个地址空间但是其中代码区的虚拟地址在页表当中 映射的是 和 父进程一样的 代码的物理地址。此时你应该就理解了为子进程和父进程之间可以有共享的 代码和大部分的共享的数据但是子进程还有自己的 独有的数据供子进程自己来维护 同理子父进程之间既然可以共享 代码那么两者之间也是可以共享 变量地址空间的。如果子进程没有修改此变量的话那么子父进程访问的是同一块变量的空间。如果子进程修改了变量的值的话那么就会发生写时拷贝在内存当中为子进程新拷贝一块空间这块空间供子进程使用。 其实如果子进程不对变量进行修改的话子父进程访问同一块空间其实和 浅拷贝有些类似如果发生修改相当于发生了深拷贝操作系统为子进程新开辟了一块空间供子进程使用。 那么相信在前言当中对于 子父进程 访问同一地址但是打印的数据却不一样的这个现象你已经有所眉目了。没错我们打印在屏幕上的这个地址不是在内存当中存储的物理地址而是自己的进程地址空间对应的 虚拟地址。 向上述子进程的 变量 空间的值是200其实刚开始不是200因为要修改之前实现在父进程的这个变量的值的基础之上来进行拷贝的所以刚开始是 0在子进程对这个值进行修改之后这个变量的值就变成 200了。  通过页表映射的方式就实现了看似是同一个虚拟地址实际上打印结果不一样的结果。其实这两个进程的虚拟地址是不一样的一个是 父进程当中的虚拟地址一个是 子进程当中的虚拟地址。两虚拟地址在各自的 页表当中的映射的是不同的 物理地址。 什么是地址空间什么是进程地址空间 地址空间的本质其实是以进程的视角来对内存进行划分的其实也就是我们说的在 内存当中的离散存储。 在计算机当中有很多的 设备把这些各种设备连接起来那么设备和设备之间内存和外设之间cpu和内存之间一定要做到数据的交互。那么这些个设备要进行数据的通讯就要用“线”来连接起来。这些“线”实际上可以划分成三类地址总线数据总线控制总线。 cpu 和 内存之间连线的叫做系统总线内存和外设之间连接叫做 IO总线。我们需要这些先把数据从一个设备拷贝到另一个设备当中。在 32 位机器当中cpu 和 内存是通过总线直接相连的。 每一根相连的总线有两个信息就是 0/1 。在内存当中就可以更具每一根总线上不同的信息来得到不同的 数据也就得到不同的地址。 在内存当中有一个 可以更具cpu 通过总线发出的不同信息解析出地址的设备可以理解为 地址寄存器。在 32 位机器当中这个机器就会根据总线的当中给出的不同信息。总线通过给触发器给一个电脉冲这个触发器就可以给某一个存储单元当中充一个强电频。不充电就没有电流。 所以在地址寄存器当中可以理解为总线就是给这个设备充放电。其中有电时候就是高电频1没电就是 低电频或者没电频0。 所以地址寄存器就可以从总线给出的信息当中解析出地址。其实就是告诉内存此时cpu是要访问哪一个地址处的数据。 所以从总线当中 0/1 数据其实就是 高低电频是cpu在对内存充放电内存当中可以读取这个高低电频就是把这些高低电频所代表的二进制数据进行组合形成了物理地址。识别到当前是要访问哪一个地址上述数据这就转换成了物理地址。 那么像上述的 32 位的寄存器就是有 32 个比特级别的存储单元其实就是一个一个的触发器。 其实内存在接收到cpu 发来的地址从这个地址当中读取到数据吗要发送到 cpu 当中只是实际上也是 内存 给 cpu 充电的过程。cpu 当中寄存器就可以识别到 这种不同组合的 高低电频。cpu 就可以识别这些 0/1 数据了。 本质上在各个设备之间的数据拷贝的过程就是一个设备给另一个设备充放电的过程。 所以如果是 32 位 的机器总线就有 32 根这32 根 可以表示的数据个数 就是 2^32 次方个。 我们把 地址总线排列组合形成的地址范围如上 32 位机器 是 [0 , 2^32]。我们把这个范围叫做 地址空间。就是一段数据范围。 通俗一点来说就是一个进程在最极限的访问情况下这个进程能访问的物理内存的最大空间范围。 比如现在有两个进程管理一个内存的当中的空间的使用是有各一个对象来专门维护的在这个 对象当中是有类似的两个 维护这个进程的 地址空间的两个指针也可能是指向 这个数组空间的某个下标变量。 把 内存的地址空间分隔成大小不一的多个区域我们把这个操作称之为 -- 区域划分。 比如下面这两个进程 A 和 B   上述是把每一个 进程 的起始地址和 终止地址划分得比较清楚 的当然如果嫌麻烦还可以直接定义一个 destop_area 结构体对象在这个结构体对象当中直接存储 各个进程的 起始地址和 终止地址   有了上述结构体对象来维护 各个 进程的地址空间大小那么当我们想要修改某一个 进程 的进程大小的话就可以直接修改在 这个结构体对象当中的 对应进程的指针指向来修改 假设现在是 A 要腾出空间给 B 来使用的话我们就可以这样做   上诉是 操作系统给这个进程分配了一个 空间供这个 进程使用这个空间当中的任何一个位都是可以供这个进程任意使用的。比如可以在第一个地址位置开始存储一个 int 类型的变量在 第10个地址处存储了一个 double 类型的变量 也就是说在这个范围之内连续的空间当中每一个最小单位都可以有地址这个地址可以被这个进程正常使用。 所以什么是地址空间呢 进程地址空间本质上是一个描述进程可视范围的大小在地址空间内一定要存在各种区域的划分对现行地址进行类似 start 和 end 方式的维护。 每一个进程都要有自己的 进程地址空间的所以操作系统要管理这个进程除了来创建这个进程的 PCB 对象还要创建一个维护 这个进程的 进程地址空间的 结构体。 所以所谓地址空间本质是一个内核当中的 一个 结构体对象这个对象类似于 PCB 对象一样是要被 操作系统来管理的 。和上述说明的 如果 管理 进程地址空间一样对进程的地址空间进行先描述在组织。 但是不可能直接像上述一样只使用两个指针来维护这个进程通过前言当中的描述我们还发现一个进程当中不是仅仅一个 空间怎么简单其中还有 比如 全局数据区代码区栈区堆区等等。 这些进程地址空间当中的各种区也不是仅仅存储在一个连续的空间当中的很多情况都是离散存储的当我们想要找到一个 进程当中的 某一个区当中的某一些数据的话只需要通过页表对应的 虚拟地址 和 物理地址的键值对来找到某一个数据所在地址。 所以地址空间想要维护这个一个 进程 当中离散存储的 各个区的话就要使用多个指针来维护这些区在 内存物理地址当中存储的 起始地址和 终止地址 struct mm_struct {long code_start;long code_end;long readonly_start;long readonly_end;long init_start;long init_end;long uninit_startlong uninit_end;long heap_start;long heap_end;long stack_start;long stack_end; } 像上述的 就是一个 进程地址空间当中使用结构体维护的方式在这个进程的PCB 当中一定是有一个 指针或者是直接由上述的一个结构体对象 通过这种方式知道 这个进程的 各个区 在内存当中是如何存储的 。 我们把这个 mm_struct 这个结构体对象称之为 -- 进程地址空间。 而且不要忘记了在这个结构体当中维护的 各个区的连续空间当中每一个 最小单位都可以有地址这个地址可以被 这个进程 直接使用。 为什么要有进程地址空间 你可以很明显的认识到在现实当中使用计算机我们的很多进程是基本不可能吧全部的内存占用完的因为内存相对于 进程 来说还是蛮大的。 那么对于进程来说他就可以认为是 内存都是供我使用的进程以为整个内存都是他的但是实际上内存当中的空间很大内存可以给很多个进程分配空间。所以而 进程使用的空间大小是相对于 总内存资源来说是很少的所以对于进程来说很多时候只要是 内存资源够用的话进程基本上都是有求必应的。进程就会想当然的以为整个内存资源都是够我使用的。 但是就算内存相对于 进程来说是一个 无私的富二代进程向 内存 讨要资源之时基本都是给的但是富二代也是有最大资源的他的前也不是大风刮来的 总是有限的。所以不排除有进程 像申请特别多的资源以至于 内存都不能给予的情况。 但是这种情况一般内存是不给申请资源的而且这种情况很少一般进程的需求都是有求必应的。 我们知道在内存当中为了能够更好的利用空间而且更高效的访问空间那么每一个进程的各个存储数据的区域不是直接存储在一个 连续的 地址空间当中的而是离散式的存储各个区的数据。所以在内存当中对于数据的存储是没有规律的在进程看来是冗余的。所以为了进程更好的在内存当中访问自己的数据就有了 进程地址空间这个存储各个 区 在内存当中的  起始地址 和 终止地址的两个地址的 变量。 如果让进程直接访问到 内存当中的资源那么进程是有可能会访问越界的进程奔溃了都是小事 修改到其他进程的数据才是大事。但是在进程地址空间 和 页表管理的内存空间当中不仅仅是虚拟地址映射到 内存的 物理地址解决 内存存储复杂的问题而且还会存储这个 进程的 各个区当中 有多少可以使用的 空间资源。这样不仅可以更好的管理的进程对内存空间的使用而且还有效的防止了访问越界修改到其他资源的问题。 有了 进程地址空间 和 页表之后如果 当前你在 进程地址空间当中访问的 虚拟地址还没有申请或者是申请了但是在页表当中没有对应的映射关系又或者是映射的物理地址是只读的不能修改那么都是不能够访问这个物理空间的。 所以增加的进程地址空间可以让我们在访问内存的时候增加一个 由 虚拟地址 向 物理地址的转换看似是麻烦了其实在进程看来更加统一了而且在转换的过程当中可以对访问的 虚拟地址 或者 是 物理地址进行检查如果如果有异常的访问就会拦截该请求不会到达物理空间。依次来保护内存物理地址空间。 而且有了 进程地址空间之后在进程的视角看来整个内存空间就是 这个进程所使用 的 进程地址空间 的排列布局。这样的话在进程看来不管内存当中的资源如何进行分布在进程而言都是 进程自己的 地址空间的 排列布局。其中的数据虽然是虚拟地址但是有页表可以通过页表来找到这个 这个虚拟地址  对应 的 物理地址从而在 内存当中找到这个 这个数据在内存当中存储的位置。 所以不管是父进程还是子进程还是各种的兄弟进程在他们看来对于内存当中资源是归自己所有的而且排列布局也是按照 自己的 进程地址空间来排列布局的。 关于页表 在上述章节当中我们多次提到了 页表这个概念那么页表究竟是什么呢 页表的作用在上述也说过了就是那来 把 虚拟地址 映射到 物理地址的那么操作系统是如何访问这个页表的呢这个页表是存储在哪儿的呢 其实在cpu 当中有一个 寄存器 -- cr3在 x86 机器当中这个寄存器这个cr3 寄存器 当中存储的是 页表的起始地址。 所以当前正在运行的 进程 对应页表可以通过这个 cr3 寄存器来找到。 如果某一时刻某一个进程的被切换走了在进程再次切换回cpu 运行之时是不用担心找不到这个页表一定可以找到。因为在 cr3 这个寄存器当中存储的 页表地址本质上其实是 属于这个进程的 硬件上下文。也就是说如果进程被切换走了进程是要把自己的上下文带走的那么这个 cr3 寄存器当中存储的 内容也是要被 进程带走的。当进程切换回来的时候就会把自己进程对应的 上下文重新加载到内存或者是 寄存器当中。所以根本不用担忧。 在上述所说 cr3 寄存器当中存储的 页表地址是物理地址。很正常这些是属于靠硬件上的信息了如果上诉保存 页表地址也是虚拟地址的话就套娃了无限循环了 在上述也说过通过页表可以知道当前要访问物理地址空间在 进程地址空间当中的权限是只读权限比如 字符常量区还是可读可写的。 所以在页表当中还有一个 关键字叫做标识符这个标识符就表示了当前访问的物理地址空间的访问权限是什么。 比如上述的 0x1111 这个虚拟地址如果对这个地址的数据进行修改的话操作系统识别到你想访问这个地址的数据但是页表显示这个 地址的数据是只读的。所以直接拦截这个操作继续执行。现在这个进程相当于是进行了一次非法操作操作系统直接干掉这个进程。 所以页表可以给我们提供一个很好的访问权限管理。 所以现在你应该明白了为什么代码是只读的字符常量区是只读的 你知道了 代码是只读的那么请问代码是如何做到通过修改写入到物理内存而且我们在编写代码之时肯定不是一下就编写成功满足要求的。肯定是经过了很多次修改的那么为什么我们可以修改代码。写代码 实际上你也搞清楚我们在写代码和修改代码的过程当中是在哪里进行的操作没错是直接在物理内存当中直接进行操作那么物理空间是没有 访问权限 这个概念的更没有权限控制这个概念。你想写就写想读就读cpu可以直接对物理内存空间进行读写。  这些权限的概念是在 虚拟地址当中才有的实际上这些权限是在页表当中的映射之时才会起作用。为什么字符常量区 只读不可写是因为字符常量区的 虚拟地址 和 物理地址 在页表当中的 标志符 是 只读。 所以操作系统才能拦截你对 字符常量区当中的数据继续修改的操作。当前进行修改操作的进程才会挂掉。 关于 Linux 当中 进程挂起状态 的判断末尾介绍 区分 Linux 当中的 进程管理 和 内存管理 在之前的文章当中描述过如果当前操作系统管理的内存资源已经快满了就把 一些 进程的 数据和代码 这些 换出 到外设比如是磁盘当中当 排队轮到这个进程执行之时才把 外设 当中的 代码 和数据 换入 到 内存当中。 注意换出的不是 页表不是PCB更不是地址空间。而是 代码和数据。 Linux - 进程状态 - Linux 当中的进程状态是如何维护的-CSDN博客 但是 挂起确实是一种进程的状态但是在 Linux 当中是没有具体的状态来表示的挂起这个状态的比如有运行状态僵尸状态死亡状态阻塞状态挂起状态就是对阻塞状态的一种优化等等但是在 Linux 当中就是没有具体的状态来表示 挂起状态。 那么Linux 操作系统是如何来识别 进程的 挂起状态的呢换言之操作系统是怎么知道 这个进程的 代码和数据在不在 内存当中呢 平时我们在玩一些大型的游戏那么这些游戏动则 50G70G 甚至 100。内存肯定是不能 一次选哪个加载这么多的 数据到内存当中的所以一般这种大文件都是分批进行加载处理的。一块一块的根据时间片等等信息进行处理。 在分批处理的过程当中因为代码是一行一行执行的那么可能就会出现当前的 很大部分的数据没有在这一调度数据的时间片之内使用的到只是使用少部分的数据那么就会发生我们所说的没有正常去使用传入内存的数据。这其实是一种浪费时间和空间的事情。 所以实际上操作系统对于可执行文件的加载的策略其实是 --- 惰性加载的方式。 也就是操作系统承诺对某一个进程多少多少的内存空间来使用但是实际上是这个进程实际当中真正使用多少的内存空间就给申请多少空间给这个进程使用。 所以为实现上述效果和区分 进行的 挂起状态在页表当中还有一个 标识符这个标识符就表示当前 这一虚拟地址 所维护的 代码或者数据是否被加载到内存当中。 所以有了这个标识符当这个进程想通过这个 虚拟地址访问到物理地址的话先要看这个 虚拟值的 在上述的标识符位置 是 0 还是 1如果 已经加载到内存那么就直接用过物理地址访问如果没有加载到内存那么就会发生 --- 缺页中断。 缺页中断 简单说就是 找到对应的 可执行程序把这个可执行程序当中的 代码 或者 数据加载到内存当中。然后把这个加载到内存当中的物理地址填充到 页表当中 对应 虚拟地址 映射的 物理地址处。 其实子进程发生写时拷贝也是通过上述的却也中断的过程来判断是否要进行 写时拷贝的。 所以其实理论上 操作系统是可以实现 当一个进程在运行之时只给这个进程 的PCB页表进程地址空间等等用于维护这个进程的结构体等等都创建好但是对于这个进程的代码和数据都不进行加载当这个进程需要什么哪一些代码和数据的时候再发生 缺页中断来实现对这个进程的 惰性加载。 就可以实现边使用变加载的。 但是上述是极端情况实际使用当中是基本不会发生上述极端情况的。操作系统怎么说都会先把一部分的代码和数据先加载到 内存当中。运行这个进程 之前 操作系统还要预读一下这个可执行进程的格式等等。因为在创建地址空间页表当中的数据之时也是要根据可执行程序当中的格式数据来做参考的。 进程再被创建之时是先创建内核数据结构呢还是先加载对应的可执行程序呢 是要先创建内核数据结构在这基础之上再去加载对应的可执行程序。 而对于再分发生缺页中断时外存当中的数据怎么加载到内存当中加载到内存当中什么位置》把这个内存物理地址填充到页表当中是怎么填充的什么时候填充加载的数据是可执行程序的那一部分呢加载多少数据呢 这些问题其实都是由操作系统来做的这个具体操作被称之为 -- Linux内存管理模块。不是本篇博客的设计范围所以这里只是提一嘴。 所以站在进程的视角进程在自己被切换调度的时候根本就不管自己的数据啊PCB对象等等这些是在内存上如何进行存储进程是不管的他只管自己的运行之时所要处理的事情。 所以Linux 在把这些处理方式分两种一种是 进程管理另一种是 内存管理。 进程管理模块 和 内存管理模块之间的 解耦合 所以就是有了进程地址空间 和 页表的存在才有了 Linux 当中的 进程管理模块 和 内存管理模块之间的 解耦合的实现 进程想要申请空间不需要面对内存通过操作系统出面像内存进行申请即可两个模块各做各的事情不再出现强耦合的情况。 否则如果进程直接和 内存物理地址相连那么当 内存管理模块 或者 进程管理模块出现差错两者之间都会互相影响。 所以现在的进程组成task_struct mm_struct 页表 程序的代码和数据。 那么是不是就意味着当在发生进程切换的时候进程的 PCB 进程地址空间页表都要进行切换呢 其实在切换 PCB之时  这个 PCB 所匹配的地址空间自动被切换因为 PCB 指向对应的地址空间。又因为存储页表地址的寄存器 -- cr3属于进程上下文所以页表地址的这个上下文被切换那么页表也就自动被切换了。所以归根结底只要进程的上下文一被切换那么上述的三个数据都要被切换。 为什么进程之间是独立的页表存在的意义 那么为什么各个进程之间都是独立的发生解耦了呢其实是因为就算是 不同进程当中 访问同一个虚拟地址也就说就算两个进程访问的虚拟地址是一样的但是在两个页表当中 同一个 虚拟地址 映射的 物理地址也是不一样的所以访问的物理地址也就是不一样的访问的数据也是不一样的。所以进程之间就不会发生强耦合关系进程之间就是独立的。 父子进程访问代码虽然是一样的但是数据区访问的数据是不一样的那这个不就是解耦了吗那么其中某一个进程一旦异常了那么这个进程就要释放自己的 PCB 进程地址空间页表还要单独开辟的空间。但是和另一个进程共同使用的空间是不会释放的。这不就又解耦了吗 所以此时对于进程来说外存当中数据加载到内存当中什么位置加载多少就不重要了。因为有页表映射所以在数据存储到内存当中什么位置通过页表映射就可以了。内存当中存储数据可以是乱序的离散存储但是在 虚拟地址当中 这个地址可以是连续的这就叫以同一的视角来访问进程的数据和代码就可以把无序变有序这就是页表所存在的意义。
http://www.w-s-a.com/news/860138/

相关文章:

  • 维修网站怎么做跨境电商发展现状如何
  • 手机网站设计公司皆选亿企邦桐乡市建设局官方网站
  • 企业培训 电子商务网站建设 图片山东省住房和城乡建设厅网站主页
  • 做酒招代理的网站赣icp南昌网站建设
  • 怎样做网站內链大连市建设工程信息网官网
  • 网站软件免费下载安装泰安网站建设收费标准
  • 部署iis网站校园网站设计毕业设计
  • 网站快慢由什么决定塘沽手机网站建设
  • 苏州那家公司做网站比较好装修队做网站
  • 外贸网站推广中山网站流量团队
  • 网站前端设计培训做一份网站的步zou
  • 网站备案拍照茶叶网页设计素材
  • wordpress 手机商城模板关键词优化软件有哪些
  • 网站301做排名python做的网站如何部署
  • 昆山做企业网站工信部网站 备案
  • 做英文的小说网站有哪些网站做qq登录
  • 湖州建设局招投标网站深圳广告公司集中在哪里
  • 重庆主城推广网站建设商城网站建设预算
  • 宁波品牌网站推广优化公司开发公司工程部工作总结
  • 长沙建站模板微信网站建设方案
  • 不让网站在手机怎么做门户网站 模板之家
  • 网站建设及推广图片wordpress文章摘要调用
  • 手机版网站案例全国信息企业公示系统
  • 模仿别人网站建设银行广州招聘网站
  • 沧州网站建设沧州内页优化
  • 代加工网站有哪些专门做网站关键词排名
  • 郑州做景区网站建设公司软件开发者模式怎么打开
  • 长沙企业网站建设哪家好做app一般多少钱
  • 南宁一站网网络技术有限公司网站开发技术应用领域
  • 公司网站建设方案ppt专业构建网站的公司