调用一个 ILE 程序时,系统缺省情况下会立即激活该 ILE 程序直接依赖和间接依赖的所有 ILE 服务程序。从 V6R1 开始,为了提高激活性能,IBM i 提供了延迟激活。利用延迟激活,只有当 ILE 服务程序所导出的某个函数被调用时,该 ILE 服务程序才会被真正激活。此外,IBM i 支持动态激活,用户可以在运行时选择激活某个 ILE 服务程序,访问其导出的数据或者调用其导出的函数。本文将通过实例,介绍 IBM i 提供的三种程序激活方式:立即激活、延迟激活、动态激活。

涂 波, IBM i debugger developer, IBM

涂波,有 7 年在 linux/solaris 编程经验。从 2007 年加入 IBM 到现在一直在做 IBM i debugger 项目。目前他主要兴趣集中在工具链领域,包括 compiler, debugger, runtime 等等。



2012 年 9 月 10 日

调用一个 ILE 程序时,系统缺省情况下会立即激活该 ILE 程序直接依赖和间接依赖的所有 ILE 服务程序。从 V6R1 开始,为了提高激活性能,IBM i 提供了延迟激活。利用延迟激活,只有当 ILE 服务程序所导出的某个函数被调用时,该 ILE 服务程序才会被真正激活。此外,IBM i 支持动态激活,用户可以在运行时选择激活某个 ILE 服务程序,访问其导出的数据或者调用其导出的函数。本文将通过实例,介绍 IBM i 提供的三种程序激活方式:立即激活,延迟激活,动态激活。

将 ILE 程序或者 ILE 服务程序放到主存,使其能运行的过程叫做激活 (Activation)。 激活由操作系统完成,主要做两件事情:

  1. 为 ILE 程序或者 ILE 服务程序中定义的静态数据分配空间和初始化。
  2. 符号解析,获得从 ILE 服务程序中导出的符号在运行时的地址。

在某台 IBM i 机器中,创建库 ACT, 并在该库中创建文件 QCSRC,命令如清单 1。

清单 1. 创建库和文件
 CRTLIB ACT 
 CRTSRCPF FILE(ACT/QCSRC) RCDLEN(128)

在文件 ACT/QCSRC 中创建一个成员 TEST,TEST 中只有一个简单的函数 test(),代码请参考清单 2。

清单 2. 测试代码 test
   void test() 
 { 
      printf("Hello from test()! \n"); 
 }

通过下面的步骤,生成 ILE 服务程序 TEST_SRV,该服务程序存放在库 ACT 中,并且导出符号 test。

  1. CRTCMOD MODULE(ACT/TEST) SRCFILE(ACT/QCSRC)
  2. 在 ACT/QCSRC 中,创建名字为 TESTBND 的 Binder 源文件,内容图 1 所示。该文件可以通过工具 RTVBNDSRC 自动生成。
    图 1. Binder 代码
    图 1. Binder 代码
  3. CRTSRVPGM SRVPGM(ACT/TEST_SRV) MODULE(ACT/TEST) EXPORT(*SRCFILE) SRCFILE( ACT/QCSRC) SRCMBR(TESTBND)

立即激活

当调用某个 ILE 程序或者服务程序时,立即激活该 ILE 程序直接依赖和间接依赖的所有 ILE 服务程序,这种激活方式叫做立即激活。

在文件 ACT/QCSRC 中创建一个成员 IMMED,IMMED 中只有一个函数 main(),代码请参考清单 3。

清单 3. 测试代码 main
   void main() 
 { 
   test(); 
 }

运行清单 4 中的命名,编译生成程序 IMMED。CRTPGM 提供了关键字 *IMMED,为选项 BNDSRVPGM 指定关键字 *IMMED,可以实现立即激活。如果调用程序 ACT/IMMED,所依赖的服务程序 ACT/TEST_SRV 也会被同时激活。

清单 4. 编译立即激活的程序
 CRTCMOD MODULE(ACT/IMMED) SRCFILE(ACT/QCSRC) 
 CRTPGM PGM(ACT/IMMED) BNDSRVPGM((ACT/TEST_SRV *IMMED))

延迟激活

当调用某个 ILE 程序或者服务程序时,只有它依赖的某个 ILE 服务程序所导出的某个函数第一次被调用时,该 ILE 服务程序才会被真正激活。

在文件 ACT/QCSRC 中创建一个成员 DEFER, 代码如清单 5。

清单 5. 测试代码 defer
 void defer(int flag) 
 { 
   if(flag == 1) 
   test(); 
 } 
   void main() 
 { 
   int flag = 0; 
   defer(flag); 
 }

运行清单 6 中的命名,编译生成程序 DEFER。CRTPGM 提供了关键字 *DEFER,为选项 BNDSRVPGM 指定关键字 *DEFER,可以实现延迟激活。相对立即激活,延迟激活提供了更好的性能,建议在程序开发中,尽量使用延迟激活。本例子中,调用程序 ACT/DEFER 的同时,并不会激活它所依赖的服务程序 ACT/TEST_SRV。当 test() 第一次被调用时,才激活服务程序 ACT/TEST_SRV。

清单 6. 编译延迟激活的程序
 CRTCMOD MODULE(ACT/DEFER) SRCFILE(ACT/QCSRC) 
 CRTPGM PGM(ACT/DEFER) BNDSRVPGM((ACT/TEST_SRV *DEFER))

动态激活

IBM i 提供了一组 APIs,用以实现动态激活,请参考表 1。

表 1. 用以实习动态激活的 APIs
QleActBndPgm激活 ILE 程序或者 ILE 服务程序,返回 4 字节的激活标志 (Activation Mark)。
QleGetExp激活 ILE 程序或者 ILE 服务程序,获取其导出的数据或者函数指针。QleGetExp 以 4 字节激活标志作为输入参数。
QleActBndPgmLong激活 ILE 程序或者 ILE 服务程序,返回 8 字节的激活标志 。强烈建议使用此 API,尽量不要使用 QleActBndPgm。
QleGetExpLong激活 ILE 程序或者 ILE 服务程序,获取其导出的数据或者函数指针。QleGetExpLong 以 8 字节激活标志作为输入参数。强烈建议使用此 API,尽量不要使用 QleGetExp。

可以从 IBM i info center 中获取以上 APIs 的详细信息。V7R1 的 Info center 链接是 http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp

IBM i 提供了 Machine Interface(MI) 函数库,该函数库实际上是对 MI 指令的封装。利用它,我们可以方便的调用 MI 指令,获得系统级编程的能力。关于 MI 函数库,请参考 ILE C/C++ MI Library Reference。可以从 IBM i info center 下载该 Reference, 链接是 http://publib.boulder.ibm.com/infocenter/iseries/v6r1m0/topic/rzajp/sc092418.pdf。

RSLVSP 是一个封装了 MI 指令的函数,可以用来获取某个 IBM i 对象的系统指针。清单 7 是 RSLVSP 的定义。

清单 7. RSLVSP 的定义
 #include <QSYSINC/MIH/RSLVSP> 
 _SYSPTR rslvsp (_OBJ_TYPE_T obj_type, 
 _OBJ_NAME obj_name, 
 _LIB_NAME lib_name, 
 _REQ_AUTH auth);

在下面的例子中,我们利用 RSLVSP 获取 ACT/QCSRC.TEST_SRV 的系统指针,然后以该指针作为输入参数,调用 QleActBndPgmLong 来动态激活 ILE 服务程序 ACT/QCSRC.TEST_SRV, 再调用 QleGetExpLong 获取指向“test”的函数指针,最后运行函数”test”。

在文件 ACT/QCSRC 中创建一个成员 DYNAMICACT,代码如清单 8。

清单 8. DYNAMICACT 源代码
 #include <stddef.h> 
 #include <stdlib.h> 
 #include <string.h> 
 #include <mih/rslvsp.h> /* rslvsp() */ 
 #include <pointer.h> /* _SYSPTR */ 
 #include <qleawi.h> /* QleActBndPgm(),QleGetExp() */ 


 /* RTVEXP Takes the following arguments: */ 
 /* 1: INPUT: Name of *SRVPGM to activate - null terminated string */ 
 /* 2: INPUT: Library for *SRVPGM - null terminated string */ 
 /* 3: INPUT: Name of export from *SRVPGM - null terminated string */ 
 /* 4: OUTPUT: Address of procedure pointer that will store a */ 
 /* pointer to the activated export. */ 

 int rtvexp(char *srvpgm_name, char *srvpgm_lib, char *procname, 
 void ** procaddr) 
 { 
   _SYSPTR sysP; 
   _OBJ_TYPE_T objectType = WLI_SRVPGM; 
   int exportType; 
   Qus_EC_t error_code; 
   unsigned long long hdl; 
   Qle_ABP_Info_Long_t activationInfo; 
   int actInfoLen = sizeof(activationInfo); 
    memset(&error_code, 0, sizeof(error_code)); 

   sysP = rslvsp(objectType, srvpgm_name, srvpgm_lib, _AUTH_EXECUTE); 
   QleActBndPgmLong(&sysP, &hdl, &activationInfo, 
   &actInfoLen, &error_code); 
   QleGetExpLong(&hdl, 0, 0, procname, procaddr, &exportType, 
    &error_code); 
   return 0; 
 } 

 void main() 
 { 
   void (*procaddr)(); 

    rtvexp("TEST_SRV", "ACT", "test", &procaddr); 
    (*procaddr)(); 
 }

利用清单 9 的命令编译和运行 ACT/DYNAMICACT。

清单 9. 编译和运行 ACT/DYNAMICACT
 CRTCMOD MODULE(ACT/DYNAMICACT) SRCFILE(ACT/QCSRC) 
 CRTPGM PGM(ACT/DYNAMICACT) 
 CALL ACT/DYNAMICACT

运行结果如图 2,

图 2. ACT/DYNAMICACT 的运行结果
图 2. ACT/DYNAMICACT 的运行结果

本例中,程序在运行时可以利用函数 rtvexp() 选择动态激活不同的 ILE 服务程序,从而提高了灵活性和可扩展性。注意,为了节省篇幅,本例没有对异常进行处理。实际开发中,需要在 rtvexp() 中对各种可能的异常进行处理。


结束语

本文介绍了 IBM i 提供的三种程序激活方式:立即激活,延迟激活,动态激活。用户可以在项目实践中选择相应的激活方式。此外,和激活 (Activation) 关系比较密切的另一个概念是活动组 (Activation Group),参考 ILE Concept 的第三章”ILE 高级概念”以及第六章”活动组管理”,可以帮助您对 IBM i 程序激活有更多的了解。

参考资料

学习

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=IBM i
ArticleID=834289
ArticleTitle=如何激活 IBM i 程序
publish-date=09102012