分段机制(个人理解)

分段机制可用于实现多种系统设计。这些设计范围从使用分段机制的最小功能来保护程序的平坦模型,到使用分段机制创建一个可同时可靠地运行多个程序(或任务)的具有稳固操作环境的多段模型。

多段模型能够利用分段机制全部功能提供由硬件增强的代码,数据结构,程序和任务的保护措施。通常,每个程序(或任务)都是用自己的段描述符以及自己的段。对程序来说段能够完全是私有的,或者是程序之间共享的。对所有段以及系统上运行程序各自执行环境的访问都由硬件控制。

访问检查不仅能够用来保护对段界限以外地址的引用,而且也能用来在某些段中防止执行不允许的操作。例如,因为代码段被设计成是只读形式的段,因此可以用硬件来防止对代码段执行写操作。段中的访问权限信息也可以用来设置保护环或级别。保护级别可用于保护操作系统程序不受应用程序非法访问。

  1. 段的定义  : 保护模式中的80x86 提供了4GB 的物理地址空间。这是处理器在其地址总线上可以寻址的地址空间。这个地址空间是平坦的,地址范围从0 到 0xFFFFffff .这个物理地址空间可以映射到读写内存,只读内存以及内存映射I/O中。 分段机制就是把 虚拟地址空间中的虚拟内存组织成一些长度可变的称为段的内存块单元。80386 虚拟地址空间中的虚拟地址(逻辑地址)由一个段部分和一个偏移部分构成。段是虚拟地址到线性地址转换机制的基础。每个段由三个参数定义:

    1. 段基地址(Base address),指定段在线性地址空间中的开始地址。基地址是线性地址,对应于段中偏移0 处。
    2. 段限长(limit),是虚拟地址空间中段内最大可用偏移位置。它定义了段的长度。
    3. 段属性(Attributes),指定段的特性。例如该段是否可读,可写或可作为一个程序执行:段的特权级等。
  2. 段限长定义了在虚拟地址空间中段的大小。段基址和段限长定义了段所映射的线性地址范围或区域。 段内0 到 limit 的地址范围对应线性地址中年范围 base 到 base + limit 。偏移量大于段限长的虚拟地址是无意义的,如果使用则会导致异常。另外 ,若访问一个段并没有得到段属性许可则也会导致异常。例如,如果你试图写一个只读的段,那么80386 就会产生一个异常。 另外,多个段映射到线性地址中的范围可以部分重叠或者覆盖,甚至完全重叠,如下图所示(一个任务的Code Segment 和 Data Segment
    的段限长相同,并被映射到线性地址完全相同而重叠的区域上)。
  3. 段的基地址,段限长以及段的保护属性存储在一个称为段描述符(Segment Descriptor) 的结构项中。在逻辑地址到线性地址的转换映射过程中会使用这个段描述符。段描述符保存在内存中的段描述符表中(Descriptor table)。段描述符表是包含段描述符项的一个简单数组。 前面介绍的段选择符即用于通过指定表中一个段描述符的位置来指定相应的段。
  4. 即使利用段的最凶功能,使用逻辑地址也能访问处理器地址空间中的每个字节。逻辑地址由16 bit 的段选择符和 32 bit 的偏移量组成,如下图 4-7 所示。 段选择符指定字节所在的段,而偏移量指定该字节在段中相对于段基地址的位置。处理器会把每个逻辑地址转换成线性地址。线性地址是处理器线性地址空间中的32 bit 地址。 与物理地址空间类似,线性地址空间也是平坦的4GB 地址空间,地址范围从 0 到 0xFFFFffff。线性地址空间中含有为系统定义的所有段和系统表。  为了把逻辑地址转换为一个 线性地址,处理器会执行以下操作:
    1. 使用段选择符中的偏移值(段索引)在GDT 或LDT 表中定位相应的段描述符。(仅当一个新的段选择符加载到段寄存器中时才需要这一步)。
    2. 利用段描述符检验段的访问权限和范围,以确保该段是可访问的并且偏移量位于段界限内。
    3. 把段描述符中取得的段基地址加到偏移量上,最后形成一个线性地址。
    4. 如果没有开启分页,那么处理器直接把线性地址映射到物理地址(即线性地址被送到处理器地址总线上)。如果对线性地址空间进行了分页处理,那么就会使用二级地址转换把线性地址转换成物理地址。
  5. 段描述符表
    1. 段描述符表是段描述符的一个数组,如下图所示。描述符表的长度可变,最多可以包含8192个 8 byte 描述符。有两个描述符表: 全局描述符表GDT (Global descriptor table); 局部描述符表 LDT (Local descriptor table)。
    2. 描述符表存储在由操作系统维护着的特殊数据结构中,并且由处理器的内存管理硬件来引用。这些特殊结构应该保存在仅仅由操作系统软件访问的受保护的内存区域中,以防止应用程序修改其中的地址转换信息。 虚拟地址空间被分割成大小相等的两半。 一半由GDT 来映射变换到线性地址,另一半则由 LDT 来映射。整个虚拟地址空间共含有2^14个段: 一半空间(即2^13 个段) 是由GDT 映射的全局虚拟地址空间,另一半是由LDT 映射的局部虚拟地址空间。通过指定一个描述符表(GDT 或LDT)以及表中描述符号,我们就可以定位一个描述符。
    3. 当发生任务切换时,LDT 会更换成新任务LDT ,但是GDT 并不会改变。因此,GDT所映射的一半虚拟地址空间是系统中所有任务共有的,但是LDT 所映射的另一半则在任务切换时被改变。系统中所有任务共享的段由GDT 来映射。这样的段通常包括含有操作系统的段以及所有任务各自的包含LDT 的 特殊段。 LDT 段可以想象成属于操作系统的数据。
    4. 下图4-9 所示,一个任务中的段如何能在GDT 和 LDT 之间分开。图中共有 6个段,分别用于两个应用程序 (A 和 B)以及操作系统。系统中每个应用程序对应一个任务,并且每个任务有自己的LDT。 应用程序A 在任务A 中运行,拥有LDTa ,用来映射段 Codea 和 Dataa。 类似的,应用程序B 在任务B 中运行,使用 LDTb 来映射 Codeb 和 Datab 段。 包含操作系统内核的两个段 Codeos 和 Dataos 使用GDT 来映射,这样它们可以被两个任务所共享。两个LDT 段:
      LDTa 和 LDTb 也使用GDT来映射。 
    5. 当任务A 在运行时,可访问的段 包括LDTa 映射的Codea 和Data a 段 ,加上 GDT 映射的操作系统的段 Codeb 和 Datab。 当任务B 在运行时,可访问的段包括LDTb 映射的Code b 和Datab段,加上GDT 映射的段。
    6. 这个例子通过让每个任务使用不同的LDT,演示了虚拟地址空间如何能够被组织成隔离每个任务。当任务A在运行时,任务B的段不是虚拟地址空间的部分,因此任务A没有方法访问任务B的内存。同样的,当任务B运行时,任务A的段也不能被寻址。这种使用LDT 来隔离每个应用程序任务的方法,正是关键保护需求之一。
    7. 每个系统必须定义一个GDT,并可用于系统中所有程序或者任务。另外,可选定义一个或多个LDT。例如,可以为每个运行任务定义一个LDT,或者某些或所有任务共享一个LDT。
    8. GDT 本身并不是一个段,而是线性地址空间中的一个数据结构。GDT 的基线性地址和长度值必须加载进GDTR 寄存器中。GDT 的基地址应该进行内存 8bit 对齐,以得到最佳处理器性能。GDT 的限长以字节为单位。 与段类似,限长值加上基地址可得到最后表中最后一个字节的有效地址。限长为 0 表示有 1个有效字节。 因为段描述符总是 8byte 长,因此GDT 的限长值 应该设置成总是 8 的倍数 减1 (即 8N -1);
    9. 处理器并不使用GDT 中的第一个描述符。把这个“空描述符”的段选择符加载进一个数据段寄存器(DS,ES,FS,GS)并不会产生一个异常,但是若使用这些加载了空描述符的段选择符访问内存时就肯定会产生一般保护性异常。通过使用这个段选择符初始化段寄存器,那么意外引用未使用的段寄存器肯定会产生一个异常。
    10. LDT 表存放在LDT 类型的系统段中,此时GDT 必须含有LDT 的段描述符。如果系统支持多LDT的话,那么每个LDT都必须在GDT中有一个段描述符和段选择符。一个LDT 的段描述符可以存放在GDT表的任何地方。
    11. 访问LDT 需使用其段选择符。为了在访问LDT时减少地址转换次数,LDT的段选择符,基地址,段限长以及访问权限需要存放在LDTR寄存器中。
    12. 当保存GDTR 寄存器内容时(使用SGDT指令),一个48bit 的“伪描述符”被存储在内存中。为了在用户模式(R3)避免对齐检查出错,伪描述符应该存放在一个奇字地址处(即 地址 MOD 4 =2)。 这会让处理器先存放一个对齐的字,随后是一个对齐的双字(4 byte 对齐处)。用户模式程序通常不会保存伪描述符,但是可以通过使用这种对齐方式来避免产生一个对齐检查出错的可能性。当使用SIDT指令保存IDTR寄存器内容时也需要使用同样的对齐方式。然而,当保存LDTR 或任务寄存器(分别使用SLTR 或 STR
      指令)时,伪描述符应该存放在双字对齐的地址处(即 地址 MOD 4 = 0)。
  6. 段选择符
    1. 段选择符(或称 段选择子) 是段的一个16 bit 标识符,如下图。 段选择符并不直接指向段,而是指向段描述符表中定义段的段描述符。段选择符3个字段内容:

      1. 请求特权级 RPL(Request Privilege Level);
      2. 表指示标志TI (Table Index);
      3. 索引值(Index)。
      4. 请求特权级字段RPL 提供了段保护信息,将在后面作详细说明。表索引字段TI 用来指出包含指定段描述符的段描述符表GDT 或 LDT 。TI = 0表示描述符在GDT 中; TI =1 表示 描述符在LDT 中。 索引字段给出了描述符在GDT 或LDT 表中的索引项号。可见,选择符通过定位段表中的一个描述符来指定一个段,并且描述符中包含有访问一个段的所有信息,例如段的基地址,段长度和段属性。
      5. 例如下图4-11(a)中选择符(0x80)指定了GDT 中具有RPL =0 的段1, 其索引字段是1,TI bit  是 0, 指定GDT 表。   图4-11(b)中选择符(0x10)指定了GDT 中具有 RPL =0 的段2,其索引字段值是2, TI bit 是0, 指定GDT 表。  图 4-11(c)中选择符(0x0f)指定了LDT 中具有RPL =3 的段1,其索引字段值是1, TI bit 是1,指定LDT 表。 图 4-11(d)中选择符(0x17)指定了LDT 中具有RPL=3 的段2,其索引字段值是
        2 ,TI bit 是1,指定LDT 表。 实际上图4-11 中的前4个选择符 (a)(b)(c)(d) 分别就是Linux 0.1x kernel 的内核代码段,内核数据段,任务代码段 和 任务数据段的选择符。 图4-11 (e)的选择符(0xffff)指定LDT 表中RPL =3 的段8191.其索引字段值是0b111111111111(即使8191),TI bit 为1,指定LDT 表。 
      6. 另外,处理器不适用GDT 表中的第一项。指向GDT 该项的选择符(即索引值为0,TI 标志位0的选择符)用作为“空选择符”,见图4-11(f)所示。当把空选择符加载到一个段寄存器(除了CS 和SS 以外)中时,处理器并不产生异常。但是当使用含有空选择符的段寄存器用于访问内存时就会产生异常。当把空选择符加载到CS 或 SS 段寄存器中时将会导致一个异常。
      7. 对应用程序来说段选择符是作为指针变量的一部分而可见,但选择符的值通常是由链接编辑器或链接加载程序进行设置或修改,而非应用程序。
      8. 为减少地址转换时间和编程复杂性,处理器提供可存放最多6个段选择符的寄存器(见图4-12所示),即段寄存器。每个段寄存器支持特定类型的内存引用(代码,数据,或堆栈)。原则上执行每个程序都起码需要把有效的段选择符加载到代码段(CS),数据段(DS),堆栈段(SS)寄存器中。处理器还另外提供段。
      9. 对于访问某个段的程序,必须已经把段选择符加载到一个段寄存器中。因此,尽管一个系统可以定义很多的段,但同时只有6个段可供立即访问。若要访问其他段就需要加载这些段的选择符。
      10. 另外,为了避免每次访问内存时都去引用描述符表,去读和解码一个段描述符,每个段寄存器都有一个“可见”部分和一个“隐藏”部分(隐藏部分也被称为“描述符缓冲” 或 “影子寄存器”)。当一个段选择符被加载到一个段寄存器可见部分中时,处理器也同时把段选择符指向的段描述符中的段地址,段限长以及访问控制信息加载到段寄存器的隐藏部分中。缓冲在段寄存器(可见和隐藏部分)中的信息使得处理器可以在进行地址转换时不再需要花费时间从段描述符中读取基地址和限长值。
      11. 由于影子寄存器含有描述符信息的一个copy,因此操作系统必须确保对描述符表的改动应反映在影子寄存器中。否则描述符表中一个段的基地址或限长被修改过,但改动却没有反映到影子寄存器中。处理这种问题最简洁的方法是在对描述符表中描述符作过任何改动之后就立刻加载6个段寄存器。这将把描述符表的相应信息重新加载到影子寄存器中。
        1. 为加载段寄存器,提供了两类加载指令:  MOV , POP,LDS, LES,LSS,LGS 以及LFS 指令。这些指令显式地直接引用段寄存器;
        2. 隐式加载指令,例如使用长指针的CALL , JMP 和RET 指令, IRET ,INTn ,INTO 和INT3 等指令。这些指令在操作过程中会附带改变CS 寄存器(和某些其他段寄存器)的内容。
  7. 段描述符 : 前面已经说明了使用段选择符来定位描述符表中的一个描述符。段描述符是GDT 和LDT 表中的一个数据结构项,用于向处理器提供有关一个段的位置和大小信息以及访问控制的状态信息。每个段描述符长度 是 8byte ,含有三个主要字段: 段基地址,段限长和段属性。 段描述符通常由编译器,链接器,加载器或者操作系统来创建,但绝不是应用程序。 图4-13 所示了所有类型段描述符的一般格式。
    1. 一个段描述符中各字段和标志的含义如下: 
      1. 段限长字段LIMIT (Segment limit field) 段限长Limit 字段用于指定段的长度。处理器会把段描述符中两个段限长字段组合成一个20 bit的值,并根据颗粒度标志G 来指定段限长Limit 值得实际含义。 如果G=0,则段长度Limit 范围可从 1byte 到 1MB 字节,单位是字节。 如果 G=1,则段长度Limit 范围可从4KB 到 4GB,单位是 4kb。
      2. 基地址字段BASE (Base address field) : 该字段定义在4GB 线性地址空间中一个段字节 0 所处的位置。处理器会把3个分立的基地址字段组合形成一个 32 bit 的值。段基地址应该对齐16 byte 边界。虽然这不是要求的,但通过把程序的代码和数据段对齐在16 byte 边界上,可以让程序具有最佳性能。
      3. 段类型字段TYPE (Type field): 类型字段指定段或门(Gate)的类型,说明段的访问种类以及段的扩展方向。该字段的解释依赖于描述符类型标志S 指明是一个应用(代码或数据)描述符还是一个系统描述符。TYPE 字段的编码对代码,数据或系统描述符都不同,见图4-14所示。
      4. 描述符类型标志S(Descriptor type flag): 描述符类型标志 S 指明一个段描述符是系统段描述符(当S=0)还是代码或数据段描述符(当S=1)。
      5. 描述符特权级字段DPL (Descriptor privilege level): DPL 字段指明描述符的特权级。特权级范围从 0 到 3。 0级特权级最高,3级最低。DPL用于控制对段的访问。
      6. 段存在标志P(Segment present) : 段存在标志 P 指出一个段是在内存中(P=1)还是不在内存中(P=0)。当一个段描述符的P 标志 为0时,那么把指向这个段描述符的选择符加载进段寄存器将导致产生一个段不存在异常。内存管理软件可以使用这个标志来控制在某一给定时间实际需要把那个段加载进内存中。这个功能为虚拟存储提供了除分页机制以外的控制。图4-15给出了当 P=0 时的段描述符格式。当P标志为0时,操作系统可以自由使用格式中标注为可用(Avaliable)的字段位置来保存自己的数据,例如有关不存在段实际在什么地方的信息。
      7. D/B(默认操作大小/默认栈指针大小和/或上界限)标志(Default operation size/ default stack pointer size and / or upper bound): 根据段描述符描述的是一个可执行代码段,下扩数据段还是一个堆栈段,这个标志具有不同的功能。(对于32 bit 代码和数据段,这个标志应该总是设置为1 ; 对于16 bit 代码和数据段,这个标志被设置为0)。
      8. 颗粒度标志G(Granularity):该字段用于确定段限长字段Limit 值得单位。如果颗粒度标志位0,则段限长值得单位是字节;如果设置了颗粒度标志,则段限长值使用4kb 单位。(这个标志不影响段基地址的颗粒度,基地址的颗粒度总是字节单位)。若设置了G 标志,那么当使用段限长来检查偏移值时,并不会去检查偏移值的12 bit 最低有效位。例如,当 G=1时,段限长为0 表明有效偏移值为 0 到 4095.
      9. 可用和保留比特位(Available 按到 reserved bits): 段描述符第2个双字的位 20 可供系统软件使用; 位 21 是保留位并应该总是设置为0.
  8. 代码和数据段描述符类型:
    1. 当段描述符中S (描述符类型)标志被置位,则该描述符用于代码或数据段。此时类型字段中最高比特位(第2个双字的 位11)用于确定是数据段的描述符(复位)还是代码段的描述符(置位)。
    2. 对于数据段的描述符,类型字段的低3 位(位 8,9,10)被分别用于表示已访问A (Accessed),可写W (Write-enable)和扩展方向E (Expansion-direction),参见表4-3 中有关代码和数据段类型比特位的说明。根据可写比特位W的设置,一个数据段可以是只读的,也可以是可读可写的。
    3. 堆栈段必须是可读/可写的数据段。若使用不可写数据段的选择符加载到SS寄存器中,将导致一个一般保护异常。如果堆栈段的长度需要动态地改变,那么堆栈段可以是一个向下扩展的数据段(扩展方向标志置位)。这里,动态改变段限长将导致栈空间被添加到栈底部。
    4. 已访问比特位指明自从上次操作系统复位该位之后一个段是否被访问过。每当处理器把一个daunting的段选择符加载进段寄存器,它就会设置该位。该位需要明确地清除,否则一直保持置位状态。该位可用于虚拟内存管理和调试。
    5. 对于代码段,类型字段的低3 位被解释成已访问A(Accessed) ,可读R(Read-enable) 和一致的C(Conforming)。根据可读R标志的设置,代码段可以是只能执行,可执行/可读。当常数或其他静态数据以及指令码被放在一个ROM 中时就可以使用一个可执行、可读代码段。这里,通过使用带CS前缀的指令或者把代码段选择符加载进一个数据段寄存器(DS,ES,FS,GS),我们可以读取代码段中的数据。在保护模式下,代码段是不可写的。
    6. 代码段可以是一致性的或非一致性的。向更高特权级一致性代码段的执行控制转移,允许程序以当前特权级继续执行。想一个不同特权级的非一致性代码段的转移将导致一般保护异常,除非使用了一个调用门或任务门(有关一致性和非一致性代码段的详细信息请参考其他资料)。不访问保护设施的系统工具以及某些异常类型(例如出错,溢出)的处理过程可以存放在一致性代码段中。需要防止低特权级程序或过程访问的工具应该存放在非一致性代码段中。
    7. 所有数据段都是非一致性的,即意味着它们不能被地特权级的程序或过程访问。然而,与代码段不同,数据段可以被更高特权级的程序或过程访问,而无须使用特殊的访问门。
    8. 如果GDT 或LDT 中一个段描述符被存放在ROM 中,那么若软件或处理器试图更新(写)在ROM 中的段描述符时,处理器就会进入一个无限循环。同时,删除操作系统中任何试图修改ROM中段描述符的代码。
  9. 系统描述符类型:
    1. 当段描述符中的S 标志(描述符类型)是复位状态(0)的话,那么该描述符是一个系统描述符。处理器能够识别以下一些类型的系统段描述符:
    2. 局部描述符表(LDT)的段描述符
    3. 任务状态段(TSS)描述符
    4. 调用门描述符
    5. 中断门描述符
    6. 陷阱门描述符
    7. 任务门描述符
    8. 这些描述符类型可分为两大类:系统段描述符和门描述符。系统段描述符指向系统段(如LDT 和TSS段),门描述符就是一个“门”,对于调用,中断或陷阱门,其中含有代码段的选择段和段中程序入口点的指针;对于任务门,其中含有TSS 的段选择符。表4-4 给出了系统段描述符和门描述符类型字段的编码。
    9. 有关TSS状态段和任务门的使用方法将在任务管理中说明,调用门的使用方法将放在保护中说明;中断和陷阱门的使用方法在中断和异常处理中说明。
时间: 2024-08-27 23:18:12

分段机制(个人理解)的相关文章

操作系统篇-分段机制与GDT|LDT

|| 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.前言 在<操作系统篇-浅谈实模式与保护模式>中提到了两种模式,我们说在操作系统中,其实大部分时间是待在保护模式中的.因此若想理解操作系统程序中的启动相关的部分,必须要理解保护模式下的编程,而分段机制是保护模式编程下的基础.而且,由于实模式与保护模式的不同,对保护模式下的分段机制更需要注意. 二.线性地址 在保护模式下编程,访问内存时,需要在程序中给出段地址和偏移量,因为分段是保护模式的基本特征之一.传统上,段地址和偏移地址称为逻辑

同步机制与异步机制的理解

同步机制与异步机制的理解 同步机制即在进行输入输出时,必须等待输入输出完毕后,才能进行后面的操作. 异步传输机制就不必等待完毕就可进行其它操作. 网络上有一个比较通俗的例子:请吃饭 同步就是我叫你吃饭,你听到了就立刻跟我去,若你没有反应,那我就不停的叫你,直到你回应.(同步的特点是我不能做其他任何的事情,专心等你...个人觉得女生肯定希望遇到此类的男生吧...) 异步就是我叫了你,然后我就去吃饭了,不管你听没听见.(异步的特点是不会等待正在执行的事件结束,他就可以执行其它的事件). 看了别人的帖

Linux内存寻址之分段机制

http://blog.xiaohansong.com/2015/10/03/Linux内存寻址之分段机制/ .段的起始地址.段的长度等等,而在保护模式下则复杂一些.IA32将它们结合在一起用一个8字节的数表示,称为描述符 .IA32的一个通用的段描述符的结构从图可以看出,一个段描述符指出了段的32位基地址和20位段界限(即段长).这里我们只关注基地址和段界限,其他的属性略过. 段描述符表 各种各样的用户描述符和系统描述符,都放在对应的全局描述符表.局部描述符表和中断描述符表中.描述符表(即段表

关于Flex事件机制的理解

优点:减少同一个UI树上对象监听器数量,从而带来性能优化. 1.FLEX 事件机制是分为三个阶段. 捕获---〉目标----〉冒泡 所谓捕获:即是寻找目标的过程,是目标的父节点.注:起点是Stage,终点也是Stage. 所谓目标:即是找到目标. 所谓冒泡:可以理解为捕获的返过程. 此为官方图解. 事件的派发: Flex中可以通过dispatchEvent()方法手工派发事件, 所有UIComponent的子类都可以调用此方法.   语法:   objectInstance.dispatchEv

关于事件机制的理解

最近终于把事件机制弄明白了.和大家分享一下. 下面是定义的事件: package { import flash.events.Event; public class NBEEvent extends Event { /** * 对 */ public static const RIGHT: String = "nbe_event_right"; public function NBEEvent(type: String, bubbles: Boolean = true, cancela

[转]as3事件流机制彻底理解

题记: 看过网上一些as3事件流的教程,觉得大多都讲得不甚清楚,让人不能喝很直观的理解.而这篇教程以将事件流过程比喻成捕鱼过程,形象简单. 在此基础上对于as3事件流总算有了全面的理解.事件流机制说白了就是为了能让开发者能更好地控制事件调用顺序. addEventListener(type:String, listener:Function, useCapture:Boolean= false, priority:int= 0, useWeakReference:Boolean= false):

PHP垃圾回收机制的理解

PHP垃圾回收机制是php5之后才有的这个东西,下面我来给大家介绍一下关于PHP垃圾回收机制一些理解,希望对各位同学有所帮助. php 5.3之前使用的垃圾回收机制是单纯的"引用计数",也就是每个内存对象都分配一个计数器,当内存对象被变量引用时,计数器 1:当变量引用撤掉后,计数器-1:当计数器=0时,表明内存对象没有被使用,该内存对象则进行销毁,垃圾回收完成. "引用计数"存在问题,就是当两个或多个对象互相引用形成环状后,内存对象的计数器则不会消减为0:这时候,这

浅谈 Attention 机制的理解

什么是注意力机制? 注意力机制模仿了生物观察行为的内部过程,即一种将内部经验和外部感觉对齐从而增加部分区域的观察精细度的机制.例如人的视觉在处理一张图片时,会通过快速扫描全局图像,获得需要重点关注的目标区域,也就是注意力焦点.然后对这一区域投入更多的注意力资源,以获得更多所需要关注的目标的细节信息,并抑制其它无用信息. 图片来源:深度学习中的注意力机制,其中红色区域表示更关注的区域. Encoder-Decoder 框架 目前大多数的注意力模型都是依附在 Encoder-Decoder 框架下,

内核保护模式之分段机制

CPU的三种模式 1982年,intel推出了80286处理器,第一次提出了保护模式,在保护模式下,段寄存器中存储的不再是段基址,而是段选择子. 真正的段基址存储在描述符高速缓存中,80286处理器访问内存,不需要段寄存器左移加上偏移. 在x86体系的CPU下,支持三种模式 实模式:兼容16位CPU的模式,当前的PC系统处于实模式(16位模式)运行状态,在这种状态下软件可访问的物理内存空间不能超过1MB,且无法发挥Intel 80386以上级别的32位CPU的4GB内存管理能力.实模式将整个物理