---- 全局描述符表GDT 全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张,GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口, GDT的入口来访问GDT了。 GDT表在内存中的起始地址,表长度指明GDT表的字节长度值。 我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。 ---- 实例 1:访问GDT 当TI=0时表示段描述符在GDT中,如上图所示: ①先从GDTR寄存器中获得GDT基址。 ②然后再GDT中以段选择器高13位位置索引值得到段描述符。
二、详解 先说明一下概念 (1)全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置, 但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器 ,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。 我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。如图 ? 局部描述符表LDT LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。 三、实例(对理解非常有用) 1:访问GDT ? 段描述符在GDT中 当TI=0时表示段描述符在GDT中,如上图所示: ①先从GDTR寄存器中获得GDT基址。
切换 GDT 切换 GDT 的工作主要分两个步骤: 通过 sgdt 指令获取当前 gdtr 寄存器存储的 loader 的 GDT 存储空间首地址与界限 创建属于 kernel 的新的 GDT 存储空间 unsigned char gdt_ptr[6]; /* 0~15:Limit 16~47:Base */ DESCRIPTOR gdt[GDT_SIZE]; void copy_gdt int*)(&gdt_ptr[2]); /* 将 LOADER 中的 GDT 复制到新的 GDT 中 */ memcpy(&gdt, (void*)(*p_gdt_base), *p_gdt_limit extern gdt_ptr sgdt [gdt_ptr] ; cstart() 中将会用到 gdt_ptr call copy_gdt ; 在此函数中改变了gdt_ptr ,让它指向新的GDT lgdt [gdt_ptr] ; 使用新的GDT 4.5.
内核知识第六讲,内核编写规范,以及获取GDT表 一丶内核驱动编写规范 我们都知道,在ring3下,如果我们的程序出错了.那么就崩溃了.但是在ring0下,只要我们的程序崩溃了.那么直接就蓝屏了 四丶设置内核代码运行的CPU在那个核心上跑.并获取出来每个核心的GDT表. nCount & shift);//设置在那个线程跑 __asm { sgdt szGDT } KdPrint(("limit:%p GDT
然而此时还需要一个针对全局的,对计算机运行状态进行控制的全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置 unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; #ifndef FRTOS_GDT_H #define FRTOS_GDT_H #include "types.h" class GlobalDescriptorTable { public: class SegementDescriptor GlobalDescriptorTable(); uint16_t CodeSegementSelector(); uint16_t DataSegementSelector(); }; #endif gdt.cpp #include "gdt.h" #include "types.h" GlobalDescriptorTable::GlobalDescriptorTable() : nullSegementDescriptor
网上搜索了一圈,才觉得查看GDT、IDT、TSS这些应该是属于内核调试的。 cosmoslife/article/details/48785683)(话说这个博客的头像有点眼熟啊,会不会我上次那个安装bochs就是参考这位大牛的……) 一开始看这个博客没怎么看懂,不知道显示指定范围和查看GDT NextThread: 00000000 IdleThread: 80553840 DpcQueue: 仔细看一下,会发现里面有显示IDT、GDT 、TSS,那时候我以为这个就算查看到了吧,但是感觉又有点不相信,接着往下看,第一次看的时候没看懂下面的dd是干什么,后来好像有点懂了,这里dd后面加的是8003f000,这不就是GDT后面的值嘛,应该是它的地址了 ,那既然查看GDT是这样,那查看IDT、TSS不是也可以dd后面加它们对应的后面的数字就可以了嘛。
我们在防护器件领域拥有GDT(气体放电管)、MOV(压敏电阻)、TVS/ESD(瞬态抑制二极管/静电保护器件)等产品,并提供快捷的交期、专业成熟的技术支持。 GDT(气体放电管)GDT利用气体击穿原理,当两端电压超过击穿电压时,气体电离形成低阻抗通路,将浪涌电流泄放至地。 第二级:MOV或TVS与GDT配合,用于进一步吸收浪涌能量,并将电压钳制在网络变压器的耐受范围内。MOV与TVS的选型需考虑通流能力与钳位电压。 退耦元件GDT与MOV/TVS之间通常需要串联退耦电阻或电感,用于实现两级防护的时序配合,确保浪涌能量优先由GDT泄放。 四、防护器件系列我们提供完整的以太网接口防护器件,覆盖GDT、MOV、TVS/ESD三大类,可满足从消费级到工业级的不同防护需求。
一丶段描述符 1.1 GDT与LDT 1.1.1 段描述符之GDT表 与 LDT表的概述 GDT表 查询inter手册可以得知. 当我们在保护模式下. 进行内存访问的时候 所有的内存访问. 一个全局或者局部标志 决定了 段选择子 是指向GDT 还是 LDT. 想要访问GDT 或者LDT 要提供 段选择子以及偏移地址. 以上就是对GDT表或者 LDT表的描述 总结来说 GDT或者LDT 就是一块内存. 也可以看成一个数组. 根据长度可以确定一个GDT表示的内存有多大 2.GDT是一个数组.数组里面保存的是段描述符结构 请不要搞混概念 在这里我们就可以用驱动程序来读取 GDT了.并且我们进行打印输出即可. 3.1.3 LDTR 总结与实验 总结1 GDT的操作 1.1 获取GDT数组表.输出所有段描述符 遍历获取GDT表 只是获取GDT表的首地址.
内存中只能有一个 GDT,但却可以存在多个 LDT,如上图所示,每个 LDT 作为 GDT 中一个描述符描述的内存段。 通常,一个 LDT 用于划分一个特定任务执行过程中需要使用的内存分段。 3. 初始化 GDT 中指向 LDT 的描述符的段基址及 LDT 代码描述符段基址 ; 初始化 LDT 在 GDT 中的描述符 xor eax, eax mov ax, ds shl eax, 4 add eax 由于 GDT 描述的内存对于所有进程来说都是可见的,且具有相同权限,如果需要为每个进程单独定义权限,也可以通过定义 LDT 的方式来解决,具体做法是创建 LDT 描述符,定义独立的属性,但内存指向 GDT --------------------- [SECTION .gdt] ; GDT ; 段基址, 段界限, ; GDT界限 dd 0 ; GDT基地址 ; ------------------ GDT 选择子 ----------------- SelectorNormal
在start.c中,我们成功的把gdt_ptr的值修改了,让它的基地址字段等于在start.c中定义的gdt数组变量。 memcpy把在loader.asm中定义的GDT表复制给gdt数组了。 ] ; cstart() 中将会用到 gdt_ptr call cstart ; 在此函数中改变了gdt_ptr,让它指向新的GDT lgdt [gdt_ptr 复制到新的 GDT 中 */ memcpy(&gdt, /* New GDT */ (void*)(*((u32*)(&gdt_ptr[2 */ u16* p_gdt_limit = (u16*)(&gdt_ptr[0]); u32* p_gdt_base = (u32*)(&gdt_ptr[2]); *p_gdt_limit = GDT_SIZE * sizeof(DESCRIPTOR) - 1; *p_gdt_base = (u32)&gdt; disp_str("-----\"cstart\" ends
三、气体放电管(GDT)选型要点:直流击穿电压、弧压与续流遮断GDT是一种开关型保护器件,依靠气体电离实现导通,通流能力极强,但响应慢,且存在续流问题。1. 这是GDT响应慢的体现。弧压(Arc Voltage): GDT导通后的维持电压,通常仅10~30V。弧压极低,容易在直流电源线上形成续流——浪涌过后GDT无法自行关断,导致电源短路烧毁。2. 续流遮断——直流应用的最大陷阱在直流电源或大容量电容供电的线路中,严禁单独使用GDT! 因为弧压低于电源电压时,GDT会持续导通,直至过流烧毁。 必须采用以下措施之一:在GDT支路串联压敏电阻或TVS管,提高续流遮断电压。使用专门设计的“直流可遮断GDT将GDT用于交流线路(交流存在过零点,可自然关断)。3. 与TVS的级联配合GDT+电阻+TVS是信号端口防雷的标准组合。GDT吸收大能量,TVS精确钳位,电阻限制GDT导通后流过TVS的电流。
创建 GDT 描述符 在 GDT 中,我们依次写入数据段与堆栈段的描述符: LABEL_DESC_DATA: Descriptor 0, DataLen-1, 92h - LABEL_GDT 3. - LABEL_GDT 4.3. ; GDT界限 dd 0 ; GDT基地址 ; ------------------ GDT 选择子 ----------------- SelectorNormal - LABEL_GDT SelectorStack equ LABEL_DESC_STACK - LABEL_GDT SelectorVideo
vstart=LOADER_BASE_ADDR LOADER_STACK_TOP equ LOADER_BASE_ADDR jmp loader_start ; 构建全局描述符表和内部段描述符 GDT_BASE equ $ - GDT_BASE ; 获取GDT界限 GDT_LIMIT equ GDT_SIZE - 1 times 60 db 0 SELECTOR_CODE equ (0x0001 << 3 ) + TI_GDT + RPL0 SELECTOR_DATA equ (0x0002 << 3) + TI_GDT+ RPL0 SELECTOR_VIDEO equ (0x0003 << 3) + TI_GDT + RPL0 gdt_ptr dw GDT_LIMIT ;写入GDT界限 dd GDT_BASE ;写入GDT起始内存地址 loadermsg db '2 loader in real 加载GDT lgdt [gdt_ptr] ;3. cr0第0位置1 mov eax, cr0 or eax, 0x00000001 mov cr0, eax
系统维护了一个全局的数据结构叫GDT( Global Descriptor Table),他保存了所有进程的代码段数据段的一些信息。系统有专门的寄存器保存了GDT的地址,叫GDTR。 GDT布局如下。 ? GDT每个项(GDT描述符)对应的结构体是 ? 我们回顾task_struct结构,看到有两个属性desc_struct,和tss_struct。 他是根据进程号(进程id)计算出在GDT中的索引。可参考上图。 // nr是进程id,计算进程的ldt结构在gdt中的索引,执行该进程的时候,从GDT的第tss->ldt项中取得进程的信息。 执行进程的时候,根据进程号,算出tss在gdt的索引,然后把索引里指向的tss里的上下文也加载到对应的寄存器,tss信息中的ldt索引首先从gdt找到进程ldt结构体数据的首地址,即desc_struct
结束 GdtLen equ $ - LABEL_GDT ; GDT长度 GdtPtr dw GdtLen - 1 ; GDT界限 dd 0 ; GDT基地址 ; GDT 选择子 SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT ; END of [SECTION .gdt] 段式存储的机制是通过段寄存器和GDT中的描述符共同提供的。 如何实现由实模式到保护模式的转换 1、准备GDT 初始化GDT中各个描述符的信息。 结束 ; GDT 选择子 ;...
在 GDT 中创建 TSS 对应的描述符与选择子 3.2.1. 创建描述符 在 GDT 中添加 Ring3 堆栈段描述符。 --------------------- [SECTION .gdt] ; GDT ; 段基址, 段界限, ; GDT界限 dd 0 ; GDT基地址 ; ------------------ GDT 选择子 ----------------- SelectorNormal - LABEL_GDT SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT SelectorData equ
是一个表格中表项的号码,这个表,有可能是全局描述符表GDT,也有可能是局部描述符表LDT。 那到底是哪个表?是由段选择子从低到高的第三位来决定的,如果这一位是0,则是GDT,否则就是LDT。 特权级:Ring3 十六进制:0023 二进制:0000000000100 0 11 段序号:4 表类型:GDT 特权级:Ring3 也就是说,cs段指向的是GDT中的第3个表项,其他三个寄存器指向的是 GDT中的第4个表项。 接下来,我们来看一下这个神秘的GDT里面的内容到底是什么?很多人学了内存管理,可能还从来没看过真实的GDT里面到底是什么数据吧。 特权级:Ring3 十六进制:002B 二进制:0000000000101 0 11 段序号:5 表类型:GDT 特权级:Ring3 Linux下我没有找到可以直接用什么命令或者工具查看GDT的方式
例如 48V 直流电源端口可选 VDC=90VVDC=90V GDT。续流问题:GDT 在交流电源或带有持续直流电压的电路中,放电后可能维持导通(续流)导致短路烧毁。 交流电源端使用 GDT 必须串联 MOV 或选用无续流设计的器件。❌典型错误:在 12V 直流电源输入端单独使用 90V GDT,雷击触发后直流续流无法熄灭,GDT 持续发热起火。 ):GDT 或 MOV,泄放大电流(kA 级),残压较高(几百伏)。 严禁在未设计去耦的情况下直接将 GDT 与 TVS 并联,否则 GDT 因响应慢而几乎不工作。 能量足够:根据浪涌等级选 PPPMPPPM(TVS)或通流容量(MOV/GDT),并留 1.5 倍以上余量。高环境温度下需降额。
Core", libraryDependencies += scalaTest % Test, ) ## 覆盖一下jar包 dependencyOverrides ++= Seq( "gdt.api " % "gdt-api-aaa" % "1.0.6", "org.apache.commons" % "commons-compress" % "1.9", "gdt.api" % "api-client-core " % "2.2.6", "gdt.api" % "api-client-l5" % "1.1.2", "gdt.api" % "gdt-api-adservice" % "2.0.75", "com.alibaba" % "fastjson" % "1.2.67", "gdt.api" % "gdt-api-customer" % "1.0.69", "com.fasterxml.jackson.core " % "jackson-databind" % "2.8.11", "com.tencent.tdbank" % "TDBusSDK" % "1.2.17", "gdt.infra" % "infra-l5
内核知识第八讲,PDE,PTE,页目录表,页表的内存管理 一丶查看GDT表. 我们通过WinDbg + 虚拟机可以进行双机调试.调试一下看下GDT表 我们知道,GDT表中.存储的是存储段信息. 保存了一系列的段和内存的属性. 但是微软并没有使用. 当作GDT表的下标.进行查表. 查询GDT表. 011 查询出来下表为3,那么去GDT表的第三项进行查找. 而我们GDT表,微软没有使用它来进行进程隔离. PS: 微软因为不使用GDT表进行进程隔离,所以段选择子都是一样的.基地址都是0,我们的虚拟地址就是线性地址.