Perl 内部结构详解 -- PerlGuts Illustrated (5 GV & Stash)
GV
GV "Global Value" 或者“符号表”,存储着变量或者函数的指针GP,由GP中slot 相关的指示来决定是否存在对应这个变量相应的类型。如图所示:
GP可以在多个GV易做图享,试运行下例查看结果。
[plain]
D:\perl -MDevel::Peek -e "*test=*Dump; Dump *Dump; Dump *test"
SV = PVGV(0x285cda4) at 0x286c0dc
REFCNT = 5
FLAGS = (PADTMP,MULTI,ASSUMECV,IN_PAD,IMPORT( CV ))
NAME = "Dump"
NAMELEN = 4
GvSTASH = 0x3a8fd4 "main"
GP = 0x2864ffc
SV = 0x0
REFCNT = 2
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x0
CV = 0x2883874
CVGEN = 0x0
LINE = 67
FILE = "D:/Perl/lib/Exporter.pm"
FLAGS = 0x8e
EGV = 0x286c0dc "Dump"
SV = PVGV(0x285cf04) at 0x285a85c
REFCNT = 3
FLAGS = (MULTI,IN_PAD)
NAME = "test"
NAMELEN = 4
GvSTASH = 0x3a8fd4 "main"
GP = 0x2864ffc
SV = 0x0
REFCNT = 2
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x0
CV = 0x2883874
CVGEN = 0x0
LINE = 67
FILE = "D:/Perl/lib/Exporter.pm"
FLAGS = 0xa
EGV = 0x286c0dc "Dump"
REFCNT 引用数量,上边例子可以观察到。
EGV (effective gv) 表示创建这个GP的GV地址。
LINE 文件中行数。
FILE_HEK 在哪个文件中创建这个GV。
对应变量的GV可以用*var 来表示,字段GvSTASH 表示字段所在的命名空间,默认有一个main 命名空间。所有存储于GV中的类型都是全局的。
[plain]
D:\perl -MDevel::Peek -e "$a = 123; Dump *a"
SV = PVGV(0x285ced4) at 0x285a82c
REFCNT = 3
FLAGS = (MULTI,IN_PAD)
NAME = "a"
NAMELEN = 1
GvSTASH = 0x3a8f9c "main"
GP = 0x286438c
SV = 0x285a83c
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x0
CV = 0x0
CVGEN = 0x0
LINE = 1
FILE = "-e"
FLAGS = 0xa
EGV = 0x285a82c "a"
如果是从其它模块中引入的,则是通过Export引入main命名空间,实际指向的还是原始模块中的GV,看以下两个例子,函数Dump CV相同。
[plain]
D:\Tmp>perl -MDevel::Peek -e "Dump *Devel::Peek::Dump"
SV = PVGV(0x285c894) at 0x286c714
REFCNT = 3
FLAGS = (MULTI,IN_PAD)
NAME = "Dump"
NAMELEN = 4
GvSTASH = 0x285aa0c "Devel::Peek"
GP = 0x2874484
SV = 0x0
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x0
CV = 0x2883854
CVGEN = 0x0
LINE = 44
FILE = "D:/Perl/lib/Devel/Peek.pm"
FLAGS = 0xa
EGV = 0x286c714 "Dump"
D:\Tmp>perl -MDevel::Peek -e "Dump *Dump"
SV = PVGV(0x285cd8c) at 0x286c0f4
REFCNT = 3
FLAGS = (PADTMP,MULTI,ASSUMECV,IN_PAD,IMPORT( CV ))
NAME = "Dump"
NAMELEN = 4
GvSTASH = 0x3a8fc4 "main"
GP = 0x2864fe4
SV = 0x0
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x0
CV = 0x2883854
CVGEN = 0x0
LINE = 67
FILE = "D:/Perl/lib/Exporter.pm"
FLAGS = 0x8e
EGV = 0x286c0f4 "Dump"
Stashes www.zzzyk.com
GVs 同Stashes 共同作用实现了Perl 的命名空间,Stash 实际是HV,所有内容都指向GV。命名空间root 是defstash,指向main Stash。一个多层次模块,每一层都有一个相应的Stash。如下所示整体命名空间结构:
示例察看main 空间的内容,*:: 等同于*main::
[plain]
D:\Tmp>perl -MDevel::Peek -e "Dump *::"
SV = PVGV(0x2851fdc) at 0x3a8fe4
REFCNT = 2
FLAGS = (READONLY,MULTI,IN_PAD)
NAME = "main::"
NAMELEN = 6
GvSTASH = 0x3a8fc4 "main"
GP = 0x2852fd4
SV = 0x0
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x3a8fc4
CV = 0x0
CVGEN = 0x0
LINE = 0
FILE = ""
FLAGS = 0xa
EGV = 0x3a8fe4 "main::"
查看main 中HV 包含的内容,节选了部分来演示:
[plain]
D:\Tmp>perl -MDevel::Peek -e "Dump \%::,1000"
SV = RV(0x3a90e0) at 0x3a90d4
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x3a8fc4
SV = PVHV(0x3ae2dc) at 0x3a8fc4
REFCNT = 3
FLAGS = (OOK,SHAREKEYS)
ARRAY = 0x287b234 (0:74, 1:44, 2:8, 3:2)
hash quality = 105.9%
KEYS = 66
FILL = 54
MAX = 127
RITER = -1
EITER = 0x0
NAME = "main"
BACKREFS = 0x3a8ff4
......
Elt "Devel::" HASH = 0xfa558e0e
SV = PVGV(0x285c314) at 0x285a9cc
REFCNT = 1
FLAGS = (MULTI)
NAME = "
补充:综合编程 , 其他综合 ,