Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文
本文是x86虚拟机系列文档,供Qtum量子链团队成员以及所有感兴趣的用户阅读。( J6 {7 k# t$ h$ p, G$ a: F

2 L8 t0 y# B* S* Y1 O与EVM不同的是,在x86架构中内存使用是不连续的,内存中可能存在空白段。例如,访问0x1000处的内存可能会导致错误,因为该段内存没有被分配,但是在0x2000处可能有一些有用的内容。实际上,大多数虚拟机和CPU架构都把这作为其优势,所以EVM的内存使用方式是比较少见的。在1Mb内存还不常见的时代,8086曾规定的大多数内存都从0开始,而只读BIOS内存位于0xF0000,有时一部分内存实际上被连接到外部设备而不是RAM。0 t+ X  _& _- ~* Q7 K7 `& \
. o. K% `/ E$ s7 j
Qtum x86 虚拟机设计也运用了这个特性,以便实现某些内存区域可以共享的特性。
& m! n7 S8 j; I' H2 ~  @7 m6 ~
' s0 }2 `8 ]2 t: s$ b2 q5 W2 K- z0 m' z! a  s- O) [# w
以下是Qtum Core的内存映射(稍后详细解释):
: @8 u9 t" y) ?- k* \, Ul  应急堆栈- 0x100,长度64,读写- T$ }6 R9 \  X* k; z+ z: \8 F
l  合约代码- 0x1000,长度0x10000 (max),只读1 j  a3 E! \' H8 R& ]4 S" w
l  合约数据- 0x100000,长度0x10000 (max),读写8 X6 L, p1 ]6 t* E" r' m
l  堆栈内存- 0x200000,长度8196,读写! ~' }  U) V, U/ D( m# h' p
l  执行数据- 0xD0000000,长度待定,只读
1 y  u9 Q% r6 L* W; v% n" Q% zl  交易数据- 0xD1000000,长度可动态调整,只读
8 j" P4 w7 @4 B& l+ cl  区块链数据- 0xD2000000,长度待定,只读
' ]& U' [7 |) M( y- }/ c9 M  b* s9 M+ x1 Y5 o' ^! A
注意,各内存块可以在第一次读取时再进行初始化。即在合约需要读取数据之前,没有必要为某个内存块构造数据。首次访问类似的内存区域可能还需要额外的gas费用。
/ r$ y3 I0 f. W) g + R* V  G8 N3 r7 `; g$ W+ C
01
- `: F0 u: |2 u, I, ^  q3 p8 ^应急堆栈(Emergency stack)
% S$ `" y* V6 E+ H发生double-fault 异常时使用的应急堆栈。暂不使用,因为异常处理暂未支持。  W( |% T& k( c& E* Y9 f4 L

9 n3 m. M0 \6 J/ f) o028 _- z: G  j4 l% _) C  P+ f2 I, J( |0 K
合约代码(Contract Code)$ c0 p  u0 p6 d' }
实际加载合约代码的内存区域。出于安全性和后续优化考虑,该内存区域设置为只读。实际的大小取决于加载的合约代码大小。超出实际大小的内存只能读取不能写入,且值恒为0。1 c* |, Z4 T6 F6 Z! j( U% f. H+ }
) `! X- z" z# h% g% _6 O
03
( \: k1 u! i. J5 }5 `" f* z; h1 K合约数据(Contract Data)
6 t* e+ [4 `+ J( V; Y8 M加载合约数据的内存区域。与EVM不同的是,对于变量, 无需CPU代码指定预留内存并将其设置为该变量的值。x86中的变量只是一个指向内存地址的简单指针。加载器(loader,在普通的操作系统中对应解析器和加载器,在Qtum中,对应虚拟机的初始化进程)通过这一地址获取变量值。这在实际中非常有用,因为我们可以使用高效的原生代码 (如“memcpy”)一次性完成所有变量的初始化。变量指针最终指向该内存区域。其实际大小暂定为1Mb,但在x86虚拟机原型发布之后有可能进行调整。( |: U3 e! k! `; U6 t" o. |
- R. G+ c& Q  \9 B. |  m: |
请注意,只读数据(取决于链接器配置)存储在代码区域。普通程序中的只读数据包括字符串、常量等。' k1 l( ~! }1 K: u# U
, G) F# n" `  G9 d9 C) I
04
* z- {/ k$ ]+ u! t( z栈内存(Stack Memory)
6 l6 k. X% P% {0 j. V- a& w* \为x86调用栈保留的内存区域。调用栈用于向函数传递参数、存储返回地址、本地变量等。之所以将其他数据和栈数据进行隔离,是因为该内存区域前后都是无效内存。也就是说,一旦栈发送溢出,将很容易被检测到,因为这将导致抛出错误。显式的抛出错误在大多数情况下都比带着错误继续运行要好得多。- \* l. l" G  h5 |8 d5 G7 [8 s

1 X8 o! I( I8 D1 E4 [) X0 X05
5 m  Y7 W6 w. Q  g4 n. M调用数据(Execution Data)& k1 L- c2 G* W& o% X) L& f
只读数据,且对于每个合约调用都是特定的。这意味着当在合约中调用合约时,数据将是不同的。这些数据包括发送者地址(发起合约调用的地址)、gas limit和其他数据等。6 h/ g8 o0 \# \% M7 z

* r2 I  x; W* r8 B* ~* B$ i" i06
$ a, r; T  v" N0 q# a6 w* v& b3 [交易数据(Transaction Data)
% Z; @/ R! K) D2 \0 z: Z 动态长度数据,编码了触发此次合约调用的完整交易数据(包括交易的所有输入输出)。其中既包含了原始脚本的访问,也包含了诸如“发送了100 token到A地址”这样方便使用的数据。关于脚本的解析,qtum-x86会提供相关的辅助库函数。
; R/ n- F) N+ N8 y/ y/ |( {0 V3 K ) T! x2 D7 z! C  e2 l
07
* ?! L8 e; Y& r区块链数据(Blockchain Data)) j9 Y( ^1 Z0 a6 c6 @; S4 S
只读的全局区块链数据,对于当前区块中的所有合约为常量。包括区块的gas limit,当前区块高度,之前区块的哈希值,当前挖矿难度等数据。
# ^8 ?, D! o5 X6 f , I! l/ Y2 e1 H" v3 I' y
设计初衷
8 F/ w9 T. _1 f7 S# \8 ?之所以令上述数据可直接从内存获取,而不是通过系统调用(syscall),其主要原因有两个:7 j" x2 n/ o8 i& Z
l  系统调用都有不可忽视的安全风险# m7 V8 ^: p7 `3 |0 t. D% U& N
l  系统调用在合约代码大小、合约代码gas消耗以及虚拟机实现速度等方面,开销都比较大;
! \: l7 s- s& N
8 n  i: k# V0 f5 `6 A每个系统调用都是一个暴露合约代码的接口,大多数操作系统内核安全漏洞来自系统调用中的bug。因此,应尽量少地将系统调用暴露给虚拟机 ,减少安全风险。
8 _8 @% y  P" L
+ J2 S2 v) U; ^" X2 Y系统调用过程总体开销较大,主要体现在以下几个方面。首先,代码虽然不大,但不可忽略。用C语言进行一次系统调用至少需要30字节,其他语言也需要或多或少的消耗内存。其次,系统调用过程中开销最大的部分在于需要在系统调用和标准C接口间进行翻译,这涉及调用帮助函数,预留寄存器,从堆栈中获取数据并将它们存储在寄存器中,执行系统调用,以及最终恢复寄存器等一系列过程。上面提到的30字节只包含帮助函数部分。实际执行的总字节数明显更多,但并没有表现在合约代码尺寸中,因为该代码只编写一次,并用于每个系统调用。1 x: b% s4 N& N5 A- d9 s% m2 B

9 a0 K: [8 M8 |& Q. ~最后,除合约本身的效率问题外,每个系统调用都有可能影响虚拟机的性能。在JIT工作流中,虽然硬件CPU可以快速地缓存JIT代码和JIT编译过的合约代码,但是在离开该内存区域去运行另一段代码时,通常必须至少先清除一部分缓存,为新代码腾出空间。在一个真正使用硬件支持的虚拟化工作流中,这类操作的开销会更大,因为它可能涉及上下文切换和硬件级系统调用。这是大多数需要在虚拟机中运行的语言遇到的常见问题,包括Webassembly(据本人了解,最近Webassembly团队才在某种程度上做了一些重大改进),Javascript/V8等等。
9 A: j  Z1 C4 e3 S% I
( o4 V! w9 b4 J# \1 o, {+ Qx86虚拟机原型
( G: i+ Q, ^1 Z$ [. }6 M  s6 V; t3 N/ s2 S' \  m8 |
Qtum x86仍处在原型开发中,故本文所述的内存映射设计与最终版本可能有出入。感兴趣的读者请持续关注包括本文在内的x86系列设计文档。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李凯908 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    24