AS400服务程序笔记.doc_第1页
AS400服务程序笔记.doc_第2页
AS400服务程序笔记.doc_第3页
AS400服务程序笔记.doc_第4页
AS400服务程序笔记.doc_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Service program一 基本概念: Service program是由module和其他Service program组成的,在系统中用*SRVPGM来表示(好像是废话- -!),其包含了很多可被其他程序调用的procedure。 Service program是用by reference方式绑定,功能类似于其他语言的函数库,提供了很多procedure供其他ILE program调用。 Service program中哪些procedure可以被其他program调用,哪些不可以呢?这就牵扯到了Service program中一个非常重要的概念:public interface。二 公共接口(public interface) Service program的public interface规定了哪些procedure和data item可以被外界使用,哪些不可。如果public interface设置的不合理,很容易产生program与Service program不兼容的问题,导致程序发生异常。那么如何定义Service program的public interface呢,如下: CRTSRVPGM命令的EXPROT参数规定了Service program如何对外提供接口,并提供2个参数值: 1 EXPORT (*ALL)。选择*all的话,那么Service program里所有使用key word:EXPORT修饰的procedure和data item都可以被外界程序使用。 2 EXPROT(*SRCFILE)。*SRCFILE是默认的参数值。使用*SRCFILE的话,可以使用binder language(BND文件)来自定义public interface,自己选择哪些procedure和data item可以被外界使用(这些 procedure、data item也必须使用key word:EXPROT修饰)。 注:binder language的文件类型是BND,默认的SOURCE FILE是QSRVSRC,并且BND文件是不需要编译的。 下面说一下*ALL和*SRCFILE各自的优缺点: *ALL的优点:使用起来非常方便,不需要额外的辅助文件,Service program中所有的export procedure 和data item就都可以被其他程序调用。 *ALL的缺点:兼容性太差,无论增加或者减少Service program的export procedure、data item,都会导致program与Service program的不兼容。那么所有用到此Service program的program都需要重新绑定(UPDPGM)或者重新编译(CRTPGM)才能正常使用。就算是这种变化并不会影响程序的正常运行(比如说你向Service program中追加了一个新的procedure,并且现程序并不使用此procedure,即增加procedure不影响现在的程序运行)那么所有用到此Service program的program也要重新绑定或编译。很麻烦吧。 *SRCFILE的缺点:*SRCFILE使用起来要比*ALL麻烦些,因为要使用binder language定义BND文件才能使用。 *SRCFILE的优点:提供了很好的兼容性。即增加或者减少Service program 的 export 的procedure、data item,程序仍然运行,不需要重新编译相关的program。 那到底是什么原因产生的兼容性问题?听我慢慢道来三 signature与binder language1 signature 首先系统为Service program提供了一个类似PF的level check的功能,来检查ILE program与Service program当前的接口是否一致。大概的过程如下: 1)CRTSRVPGM时,系统会根据Service program 的export procedure、data item的数量、名称、顺序产生一个signature(类型于PF的record format ID,具有唯一性),并保存在*SRVPGM中。例如: DSPSRVPGMSRVPGM(PASS)DETAIL(*SIGNATURE) splay Service Program Information Display 1 of 1 Service program. . . . . . . . . . . . : PASS Library. . . . . . . . . . . . . . . : MYLIB Owner. . . . . . . . . . . . . . . . . : MYLIB Service program attribute. . . . . . . : RPGLE Detail . . . . . . . . . . . . . . . . . : *SIGNATURE Signatures: 0000000000000000C5F03F1A5845D322 2)CRTPGM时,会将此Service program绑定到*PGM中,同时会把Service program当前的signature值也保存在*PGM中。例如:DSPPGMPGM(PASSBY2)DETAIL(*SRVPGM) Display Program Information Service OptProgram Library Signature PASS *LIBL 0000000000000000C5F03F1A5845D322 QRNXIE QSYS D8D9D5E7C9C540404040404040404040 QRNXUTIL QSYS D8D9D5E7E4E3C9D34040404040404040 QLEAWI QSYS 44F70FABA08585397BDF0CF195F82EC1 3)当*PGM被调用的时候,PGM会激活Service program(即把Service program加入到active group中),在激活的过程中会比较*PGM中的signature值与*SRVPGM的signature值是否一致。如果一致,则程序正常运行;如果不一致,则程序出现异常。 大概就这么个过程。2与PF LEVEL CHECK(*YES/*NO)类似,你也可以指定是否进行signature的检查 1)*ALL的话,默认LVLCHK(*YES)并且不能更改,会进行检查。那么当Service program的export procedure、data item发生变化时(增加、减少),相应的signature值也发生变化了,如果不重新绑定,重新编译相关的program,那么就导致了program与Service program的signature值不一样,必然导致不兼容。 2)*SRCFILE的话,可以选择LVLCHK *YES还是*NO。选择*NO的话,就不用细说了,因为*NO不会进行signature检查无论你怎么变化procedure、data item都不要紧。因为系统根本不会对program与Service program的signature进行对比,自然不存在兼容不兼容的问题。(使用*NO要谨慎,没有系统的检查,可能会出现一下不可预知的错误)选择*YES的话,你可以在一个BND文件中,定义多个signature,只要*PGM中保存的signature值与BND文件中任意一个signature值相当,程序就可以正常运行。举个例子吧:PGM1用到了SRVPGM1SRVPGM1有2个export procedure:export P1 export P2 BND文件: STRPGMEXP PGMLVL(*CURRENT) LVLCHK(*YES) EXPORT SYMBOL(P1) EXPORT SYMBOL(P2) ENDPGMEXP假设经过编译后,PGM1可以正常调用SRVPGM1。现在SRVPGM1增加了一个export procedure,那么为了保持PGM1与SRVPGM1的兼容,我会增加一个signature,如下:BND文件: STRPGMEXP PGMLVL(*CURRENT) LVLCHK(*YES) EXPORT SYMBOL(P1) EXPORT SYMBOL(P2) EXPORT SYMBOL(P3) ENDPGMEXP STRPGMEXP PGMLVL(*PRV) LVLCHK(*YES) EXPORT SYMBOL(P1) EXPORT SYMBOL(P2) ENDPGMEXP这样的话,即使我不重新编译PGM1,PGM1也可以正常调用SRVPGM1(不过不能使用新追加的P3,只能使用*PRV的export block) 注意:signature的值是由export procedure、data item的名称、数量、顺序决定的,且具有唯一性。为了避免不兼容问题的发生,注意以下几点: 1)不要破坏原来export block中export procedure、data item的顺序和数量。 2)新追加export block(即定义多个signature)的话,新的export block必须要包含原来的export block中的内容,并且顺序、数量都不能改变。新追加的export procedure、data item要放export list的最后面。(如上面例子所示) 3)不要删除原export block中的procedure、data item 此外,还可以通过自定义signature的值,也可以解决兼容性问题,这里就不多说了。四 service program的激活 Service program不能够直接激活。调用SRVPGM的ILE PROGRAM被调用的话,那么此SRVPGM就自动被激活。 Service program的激活过程中,主要干2件事: 1 通过符号链接与物理地址的转换,完成绑定工作。 2 进行signature checking。 这两步之前都进行过详细说明,不再叙述。-补充说明五 service program的用途、目的、优势 为什么要使用service program呢?service program能给我们提供什么好处呢? 我们之所以选择service program,主要从以下2方面进行考虑: 1 采用service program,能使系统维护更加方便,提高可重用性(我认为是最主要的原因) 2 采用service program,可以节省硬盘空间,节省内存空间。 下面还是摆事实、讲道理吧 1) 可维护性: 假如说有N个程序,都会调用MOD1,不使用service program方式的话,就得使用by copy的方式绑定,即:CRTPGM (PGM1) MODULE(MOD1)。那么,如果MOD1发生变更的话,这N个程序都需要重新绑定(UPDPGM)或者编译(CRTPGM),才能使用更新后的MOD1。 如果使用service program的话,把MOD1加入到SRVPGM1中。当MOD1再次发生变更时,如果MOD1的变更不影响SRVPGM1的public interface(即PGM1与SRVPGM1仍然兼容),那么你只需要UPDSRVPGM即可,其他相关联的N个程序都不需要重新绑定或编译;如果MOD1的变更影响到了SRVPGM1的public interface的话(比如说MOD1新增加了一个export procedure,即PGM1与SRVPGM1不兼容),那么你UPDSRVPGM之后,也只需要UPDPGM(或CRTPGM)与新追加的export procedure相关的PGM即可,不需要UPDPGM所有的PGM,方便吧。 2)节省空间: 使用by copy的方式绑定,N个程序中就有N个MOD1的代码。如果使用service program,那么整个硬盘中实际上只有一个MOD1的代码,节省了硬盘空间。 而在实际运行中,所有的用户实际上是共用一份service program的代码,系统会给每个用户分配独立的静态变量区,但是代码是共用一份的。而使用by copy的方式,每个程序中,还是会包含一分MOD1的代码,这样service program也就节省了内存空间。 六 实际使用情况 如果一个procedure被多个程序调用的话,那么就应该把它加入到service program中。如果这个procedure仅仅是一次性使用的话,那么就没必要了。 我认为理想的情况是,ILE *PGM应该由一个main procedure/module(提供PEP)+ 其它service program组成。 具体的应用情况是,可以把功能类似的程序组成一个service program。比如把各种登录验证的程序,归为一个service program;各种日期转换,日期编辑的程序放到一个service program;还有各种处理代码程序,放到一个service program等。使用service program主要的一个麻烦需要注意 如何避免 Program signature violation影响signature的东西主要是Exports,包括名称,顺序等,如果exports任何一个名称或顺序有明变化,则使用到该service program的所有程序都需要重新编译一遍,否则就会发生program signatue vionation.一个service program主要是由可运行的procedure和data items组成相应地,在service program里有两类exports, 一类是procedures的 export, 一类是data items的exports,可以分别用下面两个命令看到。DSPSRVPGM SRVPGM(SVRPGMNAME) DETAIL(*PROCEXP)DSPSRVPGM SRVPGM(SVRPGMNAME) DETAIL(*DTAEXP)如果会用bind language的话, 通过指定exports的名称或顺序的话, 在创建service program时 export选项用*srcfile, 可以避免因为service program里新增加prodecure而不得不重新编译所有使用到该service program的programs的问题。 extproc和extpgm的区别 =1.调用对象 Extproc:main procedure和subprocedure Extpgm:OPM和ILE *pgm2.调用性质: Extproc:静态调用 Extpgm:动态调用3.传参方式: Extproc:by reference、by read-only reference、by value Extpgm:by reference、by read-only reference4.示例:Extproc Demo:pass1.rpgleHNOMAIN /INCLUDE QCPYSRC,PASSBY P BYVALUE B EXPORT D BYVALUE PI 40A D PARM1 2P 0 D PARM2 20A VALUE C IF PARM1 = 1 C RETURN PARM2+LIKE RPG IIIC ELSE C EVAL PARM2 = LIKE RPG C RETURN PARM2+LIKE RPG IV C ENDIF P E =pass2.rpgleD AAA PR 40A EXTPROC(BYVALUE) D A1 2P 0 D A2 20A VALUE D NUM S 2P 0 D STRING S 20A INZ(KKK) D RESULT1 S 30A C EVAL NUM = 1 C EVAL RESULT1 = AAA(NUM:STRING)C RESULT1 DSPLY C EVAL *INLR = *ON C RETURN Extpgm Demo:DDS CODE:A.T.Name+RLen+TDpB.Functions+A R ABCR A F1 10A =RPG CODE: FFilenameIPEAF.L.I.Device+.KExit+EntrFABC O E DISK C *ENTRY PLIST C PARM MLNAME 10 C MOVELMLNAME F1 C WRITEABCR C SETON LR C RETRN =RPGLE CODE:DTESTADD PR EXTPGM(ADD) D 10A D PASSSTYLE PR D P2 10A D PASSSTYLE PI D P2 10A D P1 S 10A C C CALLP TESTADD(P2) C EVAL *INLR = *ON C RETURN 关于UPDSRVPGM后,新版本module立即生效的问题 问题: 做过ILE 模式开发的同学都有过这样的经历:已经执行过的service program,重新编译了一个module后,并且更新了相应的service program (UPDSRVPGM),然后再次调用这个service program下的这个module,但是结果显示module并没有更新,举个例子:整个程序的组织结构关系,我描述的还清楚吧,现在执行:= =CALL PGM(PGMA),则会在屏幕上显示:AAA。下面把MOD1的功能改成:DSPLY BBB,即:然后重新编译MOD1、更新SRV0,重新执行CALL PGM(PGMA)得出的结果仍然是:AAA 刚才明明重新创建了MOD1,并且也进行了UPDSRVPGM,应该打印的是BBB,为什么还是AAA呢?如何才能让程序调用最新的Module呢?解决办法:1 最简单粗暴直接的办法就是sign off ,再重新登陆。2 用命令RCLACTGRP ACTGRP(QILE)下面是我对此的理解(正确性有待验证):当更新一个PGM(module)时,旧的程序版本会被系统移到QRPLOBJ这个library中。如果在更新PGM(module)时,PGM(module)恰好处于活动的状态,那么系统会自动让用户继续使用QRPLOBJ中的旧版本程序,而不会报错,当然用户也无法使用新版本的程序。当再次加载此程序的时候,才会使用新版本的程序。 那什么时候会再次加载程序?对于service program而言:1 program运行时系统会检查其activation group是否创建,若没有创建,则会创建activation group。然后系统会在activation group中检查相关的service program是否已经被激活,如果service program尚未被激活,则系统会激活service program;如果service program已经被激活,就不会再次进行激活。简单的说service program 只有在PGM首次运行的时候,才会被激活,并且此后这个service program一直处于活动状态,直到activation group被删除。(RED BOOK)2 这段完全是我个人的猜想,没找到相关的理论做支撑。当更新service program时,因为service program在第一次被调用的时候,已经被激活了,所以仅仅更新了ASP(硬盘)中的service program,而没有更新activation group中的service program。这时候最直接的想法就是让activation group重新加载service program,这样就可以把ASP中新版本的service program重新加载到activation group中了。但是系统并没有现成的命令,可以删除activation group中的service program再进行重新加载,所以我们要用SIGN OFF和RCLACTGRP来先删除activation group,这样activation group中的所有资源就都被释放掉了。然后PGM A再次运行的时候系统自动又会创建activation group,然后会重新加载service program,这样就会使用到新版本的service program了。下图为我设想的简易流程图 Data Area和Data Queue的区别分析(一) 网上流传一道题:data area和data queue的区别。我个人觉得data area和data queue除了长的比较像之外,其可比性并不大。从大的方向说,data area和data queue的共同点仅仅是二者都可以完成不同job间的通讯的功能(即数据交换),但是相同的功能还可以由 PF,user space等完成,为什么没人把它们都拿来一起比较呢?因为长的不像?hoho下面分别介绍一下Data Area和Data Queue,希望能给困惑者带来一点帮助,不对的地方欢迎指正。Data Area一 基本信息Data Area在系统中用*DTAARA来表示,实际上OS400把Data Area当作一个单独的字段。Data Area中存储的数据类型有3种,分别是*CHAR、*DEC、*LGL。它们的最大的长度分别为:*CHAR2000个字符*DEC 1个数字(最长为24 digits, 9 decimal positions。实际上长度不能超过15)*LGL 1个逻辑值(1或者0)由此可见,Data Area所能保存的信息量十分有限,对于*DEC和*LGL来说,仅仅能保存一个数值;对与*CHAR类型来说,能保存2000个字符的数据。所以,Data Area不适用于大量数据的处理。通常用Data Area来保存一些被多个job共用的控制信息。另外,Data Area仅仅是一个单独的字段,不需要像PF中那样用游标来定位记录,所以打开一个Data Area的系统开销要比打开一个PF要小的多,效率高得多。这就是Data Area最大的优点。二 使用方法Data Area的创建、删除、修改、显示可以用CL命令在命令行上操作,或者在CLP程序中操作,都比较简单,就不多说了。下面说一下在RPGLE中的使用方法。RPG中关于Data Area的操作符有以下几个:IN、OUT、*LOCK、UNLOCK,IN:读取Data AreaOUT:输出更新Data Area并解锁*LOCK: 为Data Area加上锁UNLOCK:为Data Area 解锁 下面举个例子来说明Data Area的基本操作:D Total DS DTAARA(TotDat) /定义Data AreaD Amount 8 S 2OVERLAY(Total:1) C *LOCK IN Total /读取并且锁住Data Area * / your codeC OUT Total /更新并且释放Data Area锁 ORC *LOCK IN Total /读取并且锁住Data Area * / your codeC UNLOCK Total /释放Data Area锁关于普通Data Area的锁,做个说明:1 Data Area的锁是独占只读锁(exclusive, allow read),如果某Data Area已经被锁住了,那么其他的作业只能以只读的方式访问此Data Area,不能用OUT操作。2 如果想在程序中更新Data Area,则必须先锁住此Data Area(跟UPDATE PF一个道理)。如果没有锁住Data Area,就在那么在程序中用OUT的话,程序会报错,例如:C IN Total * / your code 没有锁住data area就输出,是不可以的。C OUT Total 3 Data Area上锁可以通过1)使用*LOCK IN 方式 2)使用Data Area Data Structure方式(稍后介绍)4 Data Area 解锁可以通过1)OUT更新并解锁2)UNLOCK 解锁3)程序结束并且*INLR=*ON,则锁自然解除。三 Data Area Data Structure这种类型的Data Area有点特殊,使用起来会方便一些定义:D Total UDS DTAARA(TotDat) /定义Data AreaD Amount 8 S 2OVERLAY(Total:1)Data Area Data Structure与普通的Data Area定义有一点差异,就是在DS keyword的前面加上一个U,即:UDS使用方法:Data Area Data Structure的特别之处就在于,它隐含了两行的代码,如下:C *LOCK IN Total /读取并且锁住Data Area *C OUT Total /更新并且释放Data Area锁就是说如果定义成Data Area Data Structure的话,那么程序会自动读取并锁住此Data Area,并且在程序结束的时候,会自动输出更新Data Area并释放锁。所以如果定义成Data Area Data Structure的话,就不需要上面的两行代码了。四 *LDALocal Data Area*LDA算是一种特殊的Data Area,它是长度为1024个字节的字符串,并由系统自动为每个job创建和删除。每个job只能操作自己的*LDA,不能操作、获取其他job的*LDA的数据。就是说在同一个job内,你愿意怎么折腾都行,但是你不能共享的job的*LDA,别的JOB也不能你的JOB的*LDA。不过有一种特例,即递交出去的作业是可以继承原来作业的*LDA的内容。假如JOB A 用SBMJOB递交出了一个JOB B,那么系统会用JOB A的*LDA的内容来初始化JOB B的*LDA。因为*LDA是私有的,不用担心其他job会锁住LDA,所以LDA的读取和更新不用上锁,也不会报错。D Local DS DTAARA(*LDA) /定义*LDAD orderNum 5 Overlay(Local:5) *C IN LocalC EVAL orderNum=12345C OUT Local如果Data Area是*LDA的话,不用锁住Data Area,更新Data Area也不会报错,不是*LDA的话,以上代码就会报错。 数组与DS用法总结 ARRAY一 array与table的区别Array:可以使用下标,进行顺序访问或随即访问Table:不可以使用下标,只能顺序访问。只能以TABxxx开头。注:table虽然和array的功能相似,但是array要比table灵活很多。Table可以淘汰了,了解table的原因是维护老的代码时可能会用到。以后就不说table了。二 array的类型和key word1有三种类型的array,分别是compile time array、run time array、pre-run time array。2与array相关的key word:DIM(number) 定义数组中元素的数量ASCEND/DESCEND 元素在数组中升序/降序排序PERRCD(number) 对于compile time array每一行中元素的个数CTDATA定义compile time arrayFROMFILE/TOFILE pre-run time arrayEXTFMT 举例:/array1定义10个元素,每个长度为5D Array1 S 5 0 DIM(10)/array2是compile time array,共6行,每行3个元素,每个元素10个长度,升序排序D Array2 S 10 DIM(6) PERRCD(3) CTDATA ASCEND/compile time array要在程序的结尾定义数据* CTDATA ARRAY2Element1 Element2 Element3Element4 Element5 Element6Element7 Element8 Element9Element10注:如果compile time array的数据发生变化,那么要更改程序源代码中的元素值,并要重新编译程序。在程序的末尾要有* CTDATA 。建议使用* CTDATA array_name的方式,但是要注意array_name要与D-spec 定义的array_name要一致;仅用*CTDATA(不指定array_name)时要注意* CTDATA的数据按照D-spec定义的array的顺序进行匹配。并且两者不能混着用。3 Index:index不能为0或负数,不能大于元素个数。三 array相关的%BIF1 %Xfoot 数组求和Sum = %Xfoot(array_name)2 %LookUpxx 查找(%TLookUpxx for table) Index = %LookUpXX(argument:array:satrtindex) %LookUp 查找第一个=argument元素的index %LookUpLE 查找第一个=argument的元素index %LookUpLT 查找第一个argument/argument的元素的index %LookUpGE 查找第一个=argument的元素的index %LookUpGT 查找第一个argument的元素的index注:除了%LookUp外,使用其他的%LookUpxx的数组必须是排过序的。3 %Size 返回变量或常量所占的字节数Size = %Size(name:*all)D SmallFiled S 5P 2D MyArray S 5 DIM(%Size(Smallfield)SizeSmall = %Size(SmallField) /SizeSmall = 3 ArraySize = %Size(MyArray

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论