LDT局部描述表 2015-12-25
LDT局部描述表
ldt在实现多任务功能中,让自己的程序使用的地址空间与其他任务相互不可见。每个程序有自己的LDT.
GDT中的ldt entry
Name | Description |
Base Address | LDT的入口地址 |
Limit | LDT的大小 |
Type | 0x2 |
S | 0 系统描述 |
DPL | 0 |
P | 1 |
AVL | 0 |
L | 0 |
D/B | 0 |
G | 0 |
ldt在实现多任务功能中,让自己的程序使用的地址空间与其他任务相互不可见。每个程序有自己的LDT.
Name | Description |
Base Address | LDT的入口地址 |
Limit | LDT的大小 |
Type | 0x2 |
S | 0 系统描述 |
DPL | 0 |
P | 1 |
AVL | 0 |
L | 0 |
D/B | 0 |
G | 0 |
32位x86体系cpu支持4G虚拟地址空间而64位cpu则支持256T(理论上是16E)。分页内存允许进程访问整个虚拟内存空间, 而不是直接访问实际的物理内存(与分段的目的相似)。
前面说过分页是可选的一种内存方式, 通过设置CR0的PG位来让页转换生效。
在x86上MMU映射内存是通过连续的2张表进行的,一张叫页目录,一张叫页表。
页帧是4K-byte 为单位的连续物理内存地址
实模式下内存的地址访问限制是1M, 这是由于8086cpu的使用的寄存器是16位的 而地址总线是20位。1M = 1<<20。
现在cpu的寄存器早就不是什么16位的了,但是计算机现代计算机启动后还是采用实模式。
实模式中就有内存访问限制,要突破这个限制,计算机必须进入保护模式。
Intel 64 and IA-32 Architectures. Software Developer’s Manual. Volume 3A的第二章对GDT进行了详细的描述。
实模式中内存寻址才用方式:
Segment:Offset
Segment 是段寄存器: CS, ES, DS, FS, GS
注解
W(var)value: 将变量var赋值为value.
R(var)value: 读取变量var的值是value.
例子: W(x)1 将变量x赋值为1. R(y)3 读取变量y的值为3
严格一致性的定义:读取地址X返回的是最近写入X的值。(如果没有缓存的cpu,直接通过总线与内存交互,这时就是严格的一致性的内存模型)。
Memory Ordering指的cpu访问内存的顺序, 这个术语包含2个层面的意义, 编译时(编译器乱序)与运行时(运行时乱序)。
现今的微处理器都能通过memory ordering特性让cpu重排内存指令, 这种特性叫做out-of-order execution(最终结果是不会受到影响的。)
通过加入memory barrier来屏蔽memory ordering.
编译时memory barrier(GNU):
asm volatile(“” ::: “memory”);
或者
asm volatile (“” ::: “memory”);
运行时memory barrier(x86): asm volatile(“mfence” ::: “memory”);
栈满后每次调用将使用新的stack, 当调用返回会释放栈。如果同样的调用反复发生在循环里面 alloc/free的导致严重的消耗。
栈的申请与释放工作不会停止的(这里我的理解是每次要将当前栈大小传递给函数),都有额外的工作需要做(检查工作负担很重啊)。
原文:
Current split stack mechanism has a “hot split” problem - if the stack is almost full, a call will force a new stack chunk to be allocated. When that call returns, the new stack chunk is freed. If the same call happens repeatedly in a tight loop, the overhead of the alloc/free causes significant overhead.
Stack allocation/deallocation work is never complete with split stacks - every time the stack size passes a threshold in either direction, extra work is required.
轻量级锁(light weight lock)
当年JVM对轻量级锁的处理JVM
文中讲到monRec对于过来就是ObjectMonitor
ObjectMontor的分配操作是在Thread空间,因此没得线程安全问题。
1.不能保证栈上当前值是否是指向堆(指针),也就是会被误认. 文章Finding References in Java™ 有相关描述,原文” A conservative collector knows only that some region of memory may contain references, but doesn’t know whether or not a given value in that region is a reference.”
2.由于上面的不确定性造成在想移动对象的时候,没有办法修改栈上对应的值。因此保守GC不能出现在对象可移动的GC算法, 比如mark-compact, copy等。
精确GC(exact)的缺点
需要额外的信息来描述栈上的当前值是否是指向的堆(指针), 标记额外值有以下方式。
1.标记法(tagging) 值本身携带自描述信息
2.stack map 通过编译器找出偏移信息.
stack map 方式的 倒是常见 java使用的OopMap. golang 使用的BitVector结构(// Information from the compiler about the layout of stack frames.)
三色标记回收算法中的3个颜色分别是 白、黑、灰.三色标记回收算法大致如下:
以上步骤就是三色标记回收的理论了。 非常简单吧, 至少在STW(STOP THE WORLD)的情况下.
但是在mutator(mutator 与 collector分别是执行应用程序与执行GC)和GC同时工作的时候要满足 黑色对象只会引用灰色的对象或其他黑色对象。 变得复杂起来了。