当前位置:编程学习 > 网站相关 >>

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 = "

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,