内容


原生 z/OS 和 zOS UNIX Systems Services 之间的编程

Comments

简介

在 1994 年,MVS 4.3(一个 z/OS 老版本)提供了一种新东西:UNIX。从此以后,不具备 z/OS 知识的 UNIX 程序员可以把应用程序从其他 UNIX 系统迁移到这种大型机上,可以用 C 和 Java™ 等语言编写代码,环境中的所有东西都是他们熟悉的。它也意味着原生 z/OS 程序员可以使用 UNIX 服务完成各种任务,比如使用 TCPIP 访问 UNIX 文件,甚至调用 UNIX 程序。但是,目前大多数人仍然觉得在 UNIX Systems Services(USS)和传统 z/OS 之间有一道 “墙”,认为一个应用程序只能在其中一种环境中运行。这种看法是不对的;z/OS 允许任何应用程序使用这两种服务。

本文讨论如何编写跨越这道墙的应用程序 —— 访问 USS 服务的传统 z/OS 应用程序,或访问传统 z/OS 服务的 USS 程序。本文主要关注两种语言:High Level Assembler(HLASM,传统 z/OS 中仍然使用这种语言)和 C(UNIX 程序员喜欢的语言)。还会提到与 C 相关的一些 z/OS 问题和技术。本文把 z/OS 的 UNIX 部分称为 USS(UNIX Systems Services),把 z/OS 的 “传统” 非 USS 部分称为 “原生” z/OS。

创建和编译 C

无论在哪里构建或编译,C 程序实际上只是普通的 z/OS 高级语言程序。它们都需要创建、编译和绑定。我们先讨论 C 代码的编译。

z/OS C 编译器实际上把 C 和 C++ 编译器融为一体,而且可以从原生 z/OS 或 USS 调用。z/OS 上的 C 编译器是 C89 编译器,这个版本比其他 UNIX 系统上的编译器老一些。可以这样运行这个编译器:

  • 在 USS 中使用 C、C++ c89 命令(它们是完全相同的)
  • 在原生 z/OS 中使用标准的 ISPF 面板(如果系统程序员安装了这个面板的话)
  • 在原生 z/OS 中的 TSO/E 中使用 CC CXX 提供的 REXX 可执行程序
  • 在原生 z/OS 中使用批作业

为了告诉编译器您的程序是 C 还是 C++,需要:

  • USS:用适当的扩展名命名程序文件:program.c (小写的 C)表示 C 程序;program.C (大写的 C)表示 C++ 程序。
  • 原生 z/OS 批作业:对于 C++ 程序,使用 C 编译器的 CXX 运行时选项。C 编译器 SCCNPRC 数据集包含两组过程,可以从批作业调用它们来编译代码:CBC* 用于 C++,EBC* 用于 C。
  • 原生 z/OS TSO/E:对于 C 代码使用 CC REXX 可执行程序,对于 C++ 代码使用 CXX REXX 可执行程序。

我们来看看在使用 C 代码时的一些问题。

代码位置

C 代码(和头文件)既可以放在 USS 文件中,也可以放在原生 z/OS 数据集中(PDS、PDS/E 或 Sequential,而且可以采用固定或可变记录两种格式)。无论在哪里编译代码,都是这样的:

  • 可以在 USS 中从原生 z/OS 数据集编译 C 代码;只需使用特殊的 USS “//” 格式指定一个原生 z/OS 序列化数据集。下面这个 USS shell 命令演示编译 PDS MYHLQ.PGMS.C 中的 PGM1 程序:

    c89 -o pgm1.o "//'MYHLQ.PGMS.C(PGM1)'"

  • 通过在 SYSIN DD 语句上指定一个 PATH,可以在批作业中从 USS 文件编译 C 代码,比如 清单 1 中的示例。
    清单 1. 编译 USS 文件中的 C 代码的 JCL
    //COMPILE EXEC CCNC001,                                    
    //SYSIN   DD  PATH='/u/mydir/pgms/pgm1.c',          
    //             PATHDISP=(KEEP,KEEP),PATHOPTS=(ORDONLY)

如果决定在原生 z/OS 数据集中存储代码,那么可能需要给它分配 RECFM=VB, LRECL=256 这样的 DCB 设置(尤其是,如果要把代码迁移到另一个 UNIX 平台)。不必像 COBOL 和 HLASM 那样把代码限制在 1 到 72 列。

从 C 访问 z/OS 功能

无论是在 USS 还是原生 z/OS 中运行,C 程序都可以使用标准的 C 函数访问许多 z/OS 功能。例如,C 函数 sleep() 大致相当于 HLASM 宏 STIMER。C 编译器还提供一些 z/OS 特有的函数,比如 __cabend()(它与 HLASM ABEND 宏相同)。所有 C/C++ 函数都在 z/OS XL C/C++ Run-Time Library Reference 中有文档说明。

值得注意的一点是,可以从不在 USS 中运行的程序调用 USS 服务(比如 getpid() fork())。在这种情况下,会自动 “标记” 地址空间,对于 USS 内核而言,这种奇特的方式使它看起来像一个进程。

如果需要访问 z/OS 控制块,那么在原生 z/OS 和 USS 中都可以用 C 代码来完成。坏消息是 IBM® 没有提供映射这些控制块所需的 C 头文件。但是,也有好消息:C 编译器还附带一个 DSECT 转换实用程序,它可以把 HLASM DSECT 转换为 C 声明。清单 2 中的代码示例从 z/OS Extended CVT 控制块生成 z/OS Sysplex Name。

清单 2. 访问 z/OS 控制块的 C 代码示例
/* -----------------------------------------------------------  
       Map z/OS Control Block Structures                                
       ---------------------------------------------------------- */
    /* --- Cut down PSA Structure - just PSACVT to find our CVT - */
    struct psa {                                                        
       int psastuff[4];                /* 4 bytes before CVT Ptr  */  
       struct cvt *psacvt;      
       /* Ignore the rest of the PSA */      
    };
         
    /* --- Cut down CVT Structure - just CVTECVT to find ECVT --- */
    struct cvt {    
       char cvtstuff[140];             /* 140 bytes before ptr    */
       struct ecvt *cvtecvt;           /* Ptr to ECVT             */
       /* Ignore the rest of the CVT */  
    };
                          
    /* --- Cut down ECVT Structure - just ECVTSPLX to get Sysplex */
    struct ecvt {            
       char ecvtecvt[8];               /* 8 Bytes before Sysplex  */
       char ecvtsplx[8];               /* Sysplex Name            */
       /* Ignore the rest of the ECVT */     
    };   
              
    /* -----------------------------------------------------------  
       Variables             
       ---------------------------------------------------------- */
    struct psa *psa_ptr = 0;           /* PSA starts at address 0 */
    char sysplex[10];       
                      
    /* -----------------------------------------------------------  
       Put our Sysplex name into the sysplex variable          
       ---------------------------------------------------------- */
    strncpy(sysplex,psa_ptr->psacvt->cvtecvt->ecvtsplx,8);

在 USS 上从 C 代码访问 z/OS 文件

从 C 代码访问原生 z/OS 文件与访问 USS 文件并没有很大的不同。fopen()、fgets()、ferror()、fwrite() fclose() 等普通 C 文件函数适用于所有原生 z/OS 数据集和 UNIX 文件。但是,在使用这些函数时要记住:

  • 在对原生 z/OS 数据集使用 fopen() 函数时,必须使用 “//” 格式(例如 //'MYHLQ.MYDATASET')指定 z/OS 数据集名称,或者使用 DD:ddname 格式指定以前分配的数据集的 DDName。但是要记住,fopen() 只适用于序列化数据集。如果有一个 PDS/PDSE,那么还需要指定成员名称(例如 //'MYHLQ.MYDATASET(MEMBER)')。
  • 要记住,原生 z/OS 文件是基于记录 的。IBM z/OS C/C++ Run Time Library Reference 有时候会提到记录 I/O;这就是指原生 z/OS 数据集。因此,对于固定记录格式,会获得整个记录,包括末尾的空白。
  • 普通的 C 文件函数也适用于 VSAM 文件。z/OS 还包含一些 VSAM 特有的函数,比如 flocate() fupdate()

从 C 代码调用汇编程序

z/OS(原生 z/OS 和 USS)上的 C 程序在 Language Environment®(LE)中运行,LE 是 z/OS 提供的一组运行时库。汇编模块常常不是这样,这意味着链接(传递参数和调用/返回地址的方式)不一样。因此,在用 C 代码定义 HLASM 程序时,必须用 #pragma 语句定义不同的链接。清单 3 中的 C 代码片段定义这样的 HLASM 程序。

清单 3. 调用 HLASM 程序的 C Pragma 语句
#pragma linkage (PGM1,OS)        /* Non-LE Linkage      */                     
extern int PGM1(void *, int *);  /* Function definition */

但是,如果 HLASM 程序是 LE 兼容的,就不需要这个 #pragma 语句。

除此之外,定义和调用 HLASM 模块的过程与调用任何其他模块是一样的。

问题和提示

  1. 如果要编写需要在不同 UNIX 系统(包括 USS)上编译和运行的 C 代码,就需要使用 __MVS__ 宏。可以使用这个宏编写条件编译所需的 #ifdef 语句。清单 4 给出一个示例。
  2. 对于 USS 和原生 z/OS,默认的 C/C++ 编译器选项不一样。因此,要仔细检查将要使用的选项。
  3. z/OS C/C++ 编译器还支持编写不在 Language Environment 中运行的 C 代码,这对于用 C 代码替换 HLASM 出口非常方便。在 z/OS 1.9 之前的 z/OS 版本中,这个特性称为 Systems Programming Facility(SPC),z/OS 1.9 及更高版本把它称为 Metal C。

    注意,在使用这个特性时,只能使用一部分运行时库函数。在 IBM z/OS XL C/C++ Programming Guide (SPC)或 z/OS Metal C Programming Guide and Reference (C Metal)中可以找到更多信息。

  4. 除非指定 C 编译器 ASCII 选项,否则在 USS 中运行的所有 C 代码都是 EBCDIC(而其他所有 UNIX 系统都使用 ASCII),所以所有字符串常量都被当作 EBCDIC 对待。考虑到 USS 本身(包括 shell 命令输入和系统函数调用的结果)都采用 EBCDIC,所以这是有意义的。在编写 Java JNI 代码时,这一点尤其重要;需要把 Java 传递来的所有信息转换为 EBCDIC。
  5. 在创建对外提供函数或变量(包括 Java JNI 代码)的 DLL 时,必须导出函数或变量;这个操作不会默认完成。可以使用 #pragma export 指令或 C 编译器的 exportall 选项来完成。
  6. 在 z/OS 上进行编译时,UNIX C 程序员会遇到一个以前没有听到过的术语:XPLINK。Extra Performance Linkage(XPLINK)模块是以不同方式在调用者之间传递参数和信息的 z/OS 模块。它是 z/OS 的一个新特性,它比老式的原生 z/OS 链接快得多。但是,XPLINK 模块有一个大问题:一般情况下,不能从 XPLINK 程序调用非 XPLINK 程序,反过来也不行。要想这样做,就需要一个 HLASM “胶水” 模块。

    另外,只对于 C 和 Java 应用程序支持 XPLINK(但是也可以编写 LE XPLINK HLASM 程序)。但是,如果希望编写 64 位程序,就没有选择了;必须使用 XPLINK。

    要想创建 XPLINK 程序:

    • 必须指定 XPLINK C 编译器选项。
    • 如果要在原生 z/OS 上编译,那么必须指定 GOFF C 编译器选项。
    • 如果要在 USS 中进行绑定,那么必须指定 XPLINK 绑定器选项。
    • 如果要在原生 z/OS 中进行绑定,那么必须添加 DYNAM=DLL RENT 绑定器选项(所有 XPLINK 程序都必须是 DLL)。
    • 如果要在原生 z/OS 中进行绑定,那么必须包含 Language Environment 副文件 CELHS001 和 CELHS003。包含这两个文件的 JCL 示例见 清单 9

    关于 XPLINK 的更多信息,请参考 IBM z/OS C/C++ Programming Guide XPLink: OS/390 Extra Performance Linkage Redbook。

清单 4. 使用 __MVS__ 实现条件编译的 C 代码
#if defined(__MVS__)
/* (z/OS specific code) */
#endif

创建和汇编 HLASM

原生 HLASM 程序员都熟悉如何用标准的 ISPF 面板和批作业对 HLASM 进行汇编;但是,还可以在 USS 中使用 as 命令进行汇编。关于这个命令的更多信息,请参考 z/OS USS Command Reference

代码位置

与 C 一样,HLASM 代码既可以放在原生 z/OS 数据集中,也可以放在 USS 文件中。既可以从 USS 汇编 PDS 中的代码,也可以从批作业汇编 USS 文件,或者结合使用这两种方式。

从 HLASM 访问 USS 函数

与前面提到的 C 程序一样,HLASM 程序可以在原生 z/OS 和 USS 环境中访问 USS 服务,而不需要任何准备步骤;只需调用服务。HLASM 程序使用 Assembler Callable Services 访问这些服务(参见 IBM z/OS Unix Systems Services Programming: Assembler Callable Services Reference)。清单 5 中的代码获取当前的进程 ID 并把它放在整字字段 PROCESSID 中。这段代码从 z/OS CSRTABLE 控制块获取 getpid() 服务的地址。每个服务在这个控制块中的偏移量参见 z/OS USS Programming: Assembler Callable Services Reference

清单 5. 访问 USS 函数的 HLASM 代码
         L     R15,16                  R15 -> Common Vector Table        
         L     R15,CVTCSRT-CVT(15)     R15 -> CSRTABLE                         
         L     R15,24(R15)             R15 -> CSR slot                         
         L     R15,276(R15)            R15 = Address of getpid svc    
         CALL  (15),(PROCESSID),VL

如果不想通过控制块获得 USS 服务的地址,还有另外两种方法:

  • 对包含所需服务的模块(对于前一个示例中是 BPX1GID)执行 z/OS LOAD。
  • 链接 SYS1.CSSLIB 中的链接存根。在这种情况下,清单 5 中的代码应该改为 清单 6。在这个示例中,BPX1GID 在链接编辑时指向 SYS1.CSSLIB 中的存根,进而连接到相关的服务。
清单 6. 使用 CALL 访问 USS 函数的 HLASM 代码
CALL  BPX1GID,(PROCESSID),VL

关于 HLASM 可用的所有 USS 服务的信息,请参考 IBM z/OS UNIX System Services Programming: Assembler Callable Services Reference。在 SYS1.MACLIB 中,原生 z/OS 也为的 USS 区域提供了映射 DSECT。

从 HLASM 访问 USS 数据集

从 HLASM 访问 USS 数据集是非常容易的。有两种方法:

  1. 调用相关的 USS Assembler Callable Service。
  2. 使用 OPEN、BLDLCLOSE 等原生 z/OS BPAM 宏。更多信息参见 IBM z/OS DFSMS Using Data Sets 手册。

在默认情况下,USS 文件以 EBCDIC 格式存储信息(所以不是 ASCII;需要 EBCDIC 转换)。

从汇编程序调用 C 程序

在 USS 和原生 z/OS 两种环境中,从 HLASM 调用 C 程序的方法与调用其他高级语言(HLL)程序一样,这意味着 HLASM 程序必须是 Language Environment 程序。为此,需要按照 Language Environment 标准使用寄存器和内存,并在 HLASM 程序的开头和结尾使用 z/OS 提供的某些宏。但麻烦的是,采用的宏和标准(及其文档位置)取决于访问模式以及程序是 XPLINK 程序还是非 XPLINK 程序:

  • 如果它是 24 位或 31 位非 XPLINK 程序,就应该在开头和结尾使用 CEEENTRY CEETERM 宏。更多信息参见 IBM z/OS Language Environment Programming Guide
  • 如果它是 31 位 XPLINK 程序,就应该在开头和结尾使用 EDCXPRLG EDCXEPLG 宏。更多信息参见 IBM z/OS C/C++ Programming Guide
  • 如果它是 64 位的(这意味着它必须是 XPLINK 程序),就应该在开头和结尾使用 CELQPRLG CELQEPLG 宏。更多信息参见 IBM z/OS Language Environment Programming Guide for 64-bit Addressing Mode

问题和提示

  • 也可以在 USS 中编译和运行 Enterprise COBOL 和 Enterprise PL/I 程序。更多信息参见对应的 Programming Guides。

绑定程序

在 z/OS 中,所有 HLASM、C、PL/I 和 COBOL 程序无论在什么地方运行,都需要由 z/OS 绑定器进行绑定(即链接编辑)。绑定器可以在 USS 或原生 z/OS 中运行:

  • 在 USS 中:使用相同的 c89 函数运行 C/C++ 编译器和 z/OS 绑定器。可以单独运行它们,也可以在一次调用中一起运行。在 c89 的 -W'L,options' 标志中指定绑定选项。
  • 在 z/OS 中:使用标准的 ISPF 面板或提交批作业,使用原生 z/OS 程序员所熟悉的选项。

装载模块和对象位置

人们通常认为,模块必须驻留在运行它们的位置;对于 USS 是 USS 目录,对于原生 z/OS 是装载库/PDSE。但是,这种看法是不对的。对于 USS 应用程序,会在 USS 库路径(在环境变量中指定)和原生 z/OS 序列(依次搜索 Job Pack Area、STEPLIB DD、JOBLIB DD、LPA 和 Linklist)中搜索调用的模块。首先搜索的位置取决于 POSIX 运行时选项是 ON 还是 OFF,如果 POSIX 是 ON,就先搜索库路径;如果 POSIX 是 OFF,就先搜索原生 z/OS 库。

可以在 C 程序中使用 #pragma runopts(POSIX(ON)) 语句、JCL EXEC 参数 PARM='POSIX(ON)' 或 Language Environment 运行时选项(使用 _CEE_RUNOPTS 环境变量)设置这个选项。

同样,原生 z/OS 应用程序可以驻留在 USS 文件中。但是这种方式的问题是,只能从在 USS 中运行的程序(而且 USS 库路径指向这个目录)或者调用 USS loadhfs 服务的程序调用它们。

对象模块(已经编译/汇编,但还没有绑定的模块)也可以驻留在 PDS、PDSE 或 UNIX 库中。在绑定程序时,可以引用这些地方的对象。

执行调用的程序 —— 静态与动态

大多数程序员都会面对的一个问题是,是静态地(被调用的程序被链接编辑/绑定到同一装载模块)还是动态地(被调用的程序是在运行时装载的单独模块)调用另一个程序。

静态链接

把一个模块静态链接到程序模块有几种方法,包括:

  • 在绑定器 SYSLIN DD 中添加一个 INCLUDE 语句来手工包含这个模块(只适用于原生 z/OS)。例如:

    INCLUDE SYSLIB(INCMOD)

  • 指定绑定器 CALL 选项,让绑定步骤的 SYSLIB DD 可以使用这个模块(只适用于原生 z/OS)。
  • 在 USS c89 命令中包含模块/对象;例如,以下命令在 pgm1 中包含 incmod.o

    c89 -o pgm1 incmod.o

  • 创建一个包含所有对象文件的 USS 存档文件,并在 c89 命令中包含它;例如:

    c89 -o pgm1 incarch.a

  • 创建一个包含所有对象文件的 USS 存档文件,并在绑定器 SYSLIN DD 中使用 AUTOCALL 语句(只适用于原生 z/OS);例如:

    AUTOCALL /u/mydir/incmod.a

如果要在 C 程序中调用非 LE HLASM 程序,或者在非 DLL 程序中直接调用 DLL 模块,那么静态链接是惟一的选择。

动态链接

C 程序只能动态地链接一种新的装载模块类型,DLL(Dynamic Link Library)。DLL 不同于传统的 z/OS 装载模块。

  • 它们必须驻留在 PDSE 或 USS 文件中。
  • 它们总是可重入的(reentrant)。
  • 它们的名称长于 8 个字符。
  • 它们可以是 COBOL、PL/I、LE HLASM 或 C 模块。但是,在编译 COBOL、PL/I 或 C 时必须使用 DLL 选项,在汇编 HLASM 时必须使用 GOFF 和 RENT 选项。
  • COBOL 和 PL/I 可以静态地调用它们。
  • PL/I 程序可以使用 FETCH 动态地链接它们。
  • COBOL 程序可以使用 CALL 动态地链接它们,但是 COBOL 程序必须编译为 DLL。
  • C 程序只能通过 DLL 调用另一个程序。

创?? DLL 的方法如下:

  • 如果在原生 z/OS 中进行绑定,需要指定绑定器选项 DYNAM=DLL
  • 如果在 USS 中调用绑定器,需要指定选项 -W 'l,dll'
  • 即使模块只包含函数,也要确保代码中有一个 main() 语句。
  • 如果要在原生 z/OS 中进行绑定,那么必须包含 Language Environment 副文件 CELHS001 和 CELHS003(31 位系统;64 位系统使用 CELQS003)。执行这个任务的 JCL 示例见 清单 9

可以通过 IBM z/OS C/C++ User's Guide 了解 DLL。最后谈谈副文件。副文件是由绑定器在绑定 DLL 时自动生成的(但是也可以手工创建它)。在批作业中,副文件被发送给 SYSDEFSD DD;在 USS 中,绑定器会创建一个使用 'x' 扩展名的文件(比如 pgm1.x)。这个副文件实际上包含绑定器指令,它告诉绑定器需要使用哪个模块调用函数。对于有两个函数的模块,副文件与 清单 7 相似。

清单 7. 31 位应用程序的 z/OS 绑定器的副文件输出
      IMPORT CODE,'MODULE','My_First_Function'
      IMPORT CODE,'MODULE','My_Second_Function'

对于 64 位模块,副文件与 清单 8 相似。

清单 8. 64 位应用程序的 z/OS 绑定器的副文件输出
      IMPORT CODE64,'MODULE','My_First_Function'
      IMPORT CODE64,'MODULE','My_Second_Function'

在绑定一个动态调用 DLL 的程序时:

  • 如果要在原生 z/OS 批作业中运行绑定器,就需要在 SYSLIN DD 输入中包含副文件指令。
  • 如果要在 USS 中运行,就需要在 c89 绑定指令中添加副文件;例如:

    c89 -o pgm1 dllfile1.x

否则,在绑定程序时就会出现无法解析的外部引用。

HLASM 程序员很熟悉通过 LOAD 宏把模块装载到存储中。但是,这只适用于原生 z/OS 模块。要想从 USS 目录装载模块,就需要使用 loadhfs USS 服务。

提示和技巧

  • 可以使用 USS extattr 命令给 USS 文件中的模块授予 APF 访问权;例如:

    extattr +a mypgm

  • 在 USS 之外使用绑定器时,一定要使用 CASE=MIXED 绑定器选项;否则,所有程序名都会变成大写的。
  • 在原生 z/OS 和 USS 之间迁移 DLL 时,需要使用 z/OS 绑定器。清单 9清单 10 清单 11 中的 JCL 示例在 USS 和原生 z/OS PDSE 之间迁移一个模块。注意,对于 64 位模块,清单 9清单 10 中的 ENTRY CEESTART 语句应该改为 ENTRY CELQSTRT

    在原生 z/OS 上创建 DLL 时,必须使用 Language Environment 副文件 CELHS003 和 CELHS001。

    还可以使用 OGETX OPUTX TSO/E 命令以及 mv cp USS 命令迁移非 DLL 模块。

  • 从 z/OS 1.9 开始,可以把副文件包含在 USS 存档文件中。
  • 在 USS 中运行绑定器时,不一定要在 USS 中创建装载模块。通过在 SYSLMOD DD 中的 PATH DD 中指定输出目录,可以通过批作业在 USS 中创建模块。但是,在从 USS 调用绑定器时,很难创建原生 z/OS 装载模块。
  • 在构建 DLL 时,要导出(EXPORT)另一个程序所使用的函数/变量。这需要在 C 代码中使用 #pragma export 语句,或者指定 EXPORTALL C 编译器选项。
清单 9. 把 DLL 从 USS 迁移到 PDSE 的 JCL
//LINK    EXEC PGM=IEWBLINK,                            
// PARM='CALL,MAP,LET,LIST,COMPAT=PM4,DYNAM(DLL)'  
//SYSPRINT DD  SYSOUT=*                                 
//SYSLMOD  DD  DISP=SHR,DSN=MYHLQ.LOADLIB         
//SYSDEFSD   DD DUMMY
//INPUT    DD  PATH='/u/mydir/pgmname',          
//             PATHDISP=(KEEP,KEEP),PATHOPTS=(ORDONLY)  
//SYSLIB   DD  DSNAME=CEE.SCEEBND2,DISP=SHR             
//SYSLIN   DD  DSNAME=CEE.SCEELIB(CELHS003),DISP=SHR    
//         DD  DSNAME=CEE.SCEELIB(CELHS001),DISP=SHR    
//         DD  *                                        
 INCLUDE INPUT
 ENTRY CEESTART                                       
 NAME PGMNAME(R)
清单 10. 把非 DLL 模块从 USS 迁移到 PDSE 的 JCL
//LINK    EXEC PGM=IEWBLINK,                            
// PARM='CALL,MAP,LET,LIST'  
//SYSPRINT DD  SYSOUT=*                                 
//SYSLMOD  DD  DISP=SHR,DSN=MYHLQ.LOADLIB         
//INPUT    DD  PATH='/u/mydir/pgmname',          
//             PATHDISP=(KEEP,KEEP),PATHOPTS=(ORDONLY)  
//SYSLIN   DD  *                                        
 INCLUDE INPUT
 ENTRY CEESTART                                       
 NAME PGMNAME(R)
清单 11. 把模块从 PDSE 迁移到 USS 的 JCL
//LINK    EXEC PGM=IEWBLINK,
// PARM='CALL,MAP,LET,LIST,COMPAT=CURRENT,DYNAM(DLL)'
//SYSPRINT DD  SYSOUT=*
//SYSDEFSD DD  DUMMY
//INPUT    DD  DISP=SHR,DSN=MYHLQ.LOADLIB
//SYSLIB   DD  DSNAME=CEE.SCEEBND2,DISP=SHR
//SYSLMOD  DD  PATH='/u/mydir/pgmname',
//             PATHDISP=(KEEP,KEEP),PATHOPTS=(ORDWR,OCREAT,OTRUNC),
//             PATHMODE=(SIRWXU,SIRWXG,SIRWXO)

结束语

跨越原生 z/OS 和 USS 之间的边界是非常容易的。实际上,根本没有边界。z/OS 是一个具有两种不同接口的操作系统。因此,除了一般的问题和小麻烦之外,访问各种服务时遇到的最大问题可能是 USS 和原生 z/OS 采用的词汇有差异,您需要习惯这些差异。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX
ArticleID=354312
ArticleTitle=原生 z/OS 和 zOS UNIX Systems Services 之间的编程
publish-date=11242008