GV
GV "Global Value" 或者“符号表”,存储着变量或者函数的指针GP,由GP中slot 相关的指示来决定是否存在对应这个变量相应的类型。如图所示:
GP可以在多个GV中共享,试运行下例查看结果。
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中的类型都是全局的。
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相同。
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
GVs 同Stashes 共同作用实现了Perl 的命名空间,Stash 实际是HV,所有内容都指向GV。命名空间root 是defstash,指向main Stash。一个多层次模块,每一层都有一个相应的Stash。如下所示整体命名空间结构:
示例察看main 空间的内容,*:: 等同于*main::
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 包含的内容,节选了部分来演示:
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 = "Devel::"
NAMELEN = 7
GvSTASH = 0x3a8fc4 "main"
GP = 0x28654ac
SV = 0x0
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x285a9dc
CV = 0x0
CVGEN = 0x0
LINE = 4
FILE = "D:/Perl/lib/Devel/Peek.pm"
FLAGS = 0x2
EGV = 0x285a9cc "Devel::"
......
Elt "Dump" HASH = 0xbbea0f76
SV = PVGV(0x285cd94) at 0x286c0f4
REFCNT = 2
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"
......
Elt "main::" HASH = 0x40383f65
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::"
Elt "ENV" HASH = 0x62ffe0d6
SV = PVGV(0x285c2b4) at 0x285a55c
REFCNT = 1
FLAGS = (MULTI)
NAME = "ENV"
NAMELEN = 3
GvSTASH = 0x3a8fc4 "main"
GP = 0x285e184
SV = 0x0
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x285a56c
CV = 0x0
CVGEN = 0x0
LINE = 0
FILE = "-e"
FLAGS = 0x2
EGV = 0x285a55c "ENV"
查看多层次模块中的内容:
D:\Tmp>perl -MDevel::Peek -e "Dump \%Devel::,1000"
SV = RV(0x3a90e0) at 0x3a90d4
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x285a9dc
SV = PVHV(0x3ae57c) at 0x285a9dc
REFCNT = 2
FLAGS = (OOK,SHAREKEYS)
ARRAY = 0x2865534 (0:7, 1:1)
hash quality = 100.0%
KEYS = 1
FILL = 1
MAX = 7
RITER = -1
EITER = 0x0
NAME = "Devel"
BACKREFS = 0x285a9fc
SV = PVAV(0x3aa32c) at 0x285a9fc
REFCNT = 2
FLAGS = ()
ARRAY = 0x286561c
FILL = 0
MAX = 3
ARYLEN = 0x0
FLAGS = ()
Elt No. 0
SV = PVGV(0x285c334) at 0x285a9ec
REFCNT = 1
FLAGS = (MULTI)
NAME = "Peek::"
NAMELEN = 6
GvSTASH = 0x285a9dc "Devel"
GP = 0x28655dc
SV = 0x0
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x285aa0c
CV = 0x0
CVGEN = 0x0
LINE = 4
FILE = "D:/Perl/lib/Devel/Peek.pm"
FLAGS = 0x2
EGV = 0x285a9ec "Peek::"
Elt "Peek::" HASH = 0xf40ca9c
SV = PVGV(0x285c334) at 0x285a9ec
REFCNT = 1
FLAGS = (MULTI)
NAME = "Peek::"
NAMELEN = 6
GvSTASH = 0x285a9dc "Devel"
GP = 0x28655dc
SV = 0x0
REFCNT = 1
IO = 0x0
FORM = 0x0
AV = 0x0
HV = 0x285aa0c
CV = 0x0
CVGEN = 0x0
LINE = 4
FILE = "D:/Perl/lib/Devel/Peek.pm"
FLAGS = 0x2
EGV = 0x285a9ec "Peek::"
希望通过这一节都能对Perl的整体有一个了解,相信其他语言也有类似的概念结构来实现命名空间的引入。