关于 z/OS 和 UNIX 服务之间的关系有很多混淆,但要记住的是,这不是两个不同的东西……几乎任何任务都可以成为 UNIX 进程并进行 USS 函数调用,使用正确的设置。
所以实际上你的问题是两个问题合二为一:
- 如何将我的任务称为 UNIX 进程,以便我可以发布 USS 内核函数?
- 我的 PL/I 编译器是否与 LE 运行时以及具有使用其他 LE 语言构建的代码的对象库兼容?
第一部分——如何让你的进程被称为 UNIX 进程——非常简单。IBM 的方法要求您在调用 UNIX 函数之前连接到 USS 内核(OMVS 地址空间),但通常这会在您第一次调用 USS 函数时自动发生。
在使用 USS 之前,您确实需要进行一定数量的系统设置。当然,OMVS 本身必须是活跃的(尽管现在没有它是罕见的)。您的安全管理员需要给您一个 UID 号,并可能为您创建一个主目录。假设这部分没问题,您需要做的就是调用一个 USS 函数,现在您是一个 UNIX 服务进程。
几乎任何应用程序都可以调用 IBM 的 USS 可调用服务(即所有名称以 BPX1/BPX4 开头的模块)——所需要的只是支持标准操作系统链接的东西。事实上,这几乎就是 IBM 的运行时库所做的。一个很好的测试是调用 BPX1GPI(即 UNIX“getpid()”)...它返回您的 UNIX 进程 ID,如果您可以使其正常工作,那么您可以使用大多数其他 UNIX 服务。如果您要跟踪 LE“getpid()”实现,您会发现它只不过是 BPX1GPI 上的一个薄层,因此您没有理由不能自己调用底层函数……这适用于大多数USS 内核函数,而不仅仅是 getpid(),所以如果你不知道如何打开一个套接字,调用 BPX1SOC 总是一个很好的“计划 B”
请记住,作为 UNIX 进程和在 bash shell 之类的东西下运行是有区别的……shell 会执行设置 STDIN/OUT/ERR 等操作 - 如果您需要这些东西,您需要这样做如果您只是突然连接到 USS,这就是您自己。在设置标准文件描述符之前,您不能调用诸如 printf() 之类的东西。
一个简单的入门方法可能是自己编写一个作为 UNIX 进程运行的简短 C 程序,设置 STDIN/OUT/ERR(以及您需要的任何其他内容),然后调用您当前的 PL/I 程序。这以一种设置您需要的任何 USS 项目的方式“包装”您当前的代码,而无需在 PL/I 中执行任何此操作。您可能还会发现这是一种方便的方法来完成一些在 PL/I 中具有挑战性的事情,例如调用 DLL 函数......只需编写一个简短的 C 函数来完成您需要的操作,然后从您的 PL/我编码。
至于您问题的第二部分,如果您的 PL/I 使用 LE 运行时(除非它很旧,否则它将使用它),那么混合来自其他库的代码比听起来要简单得多。至于核心运行时的东西,在大多数情况下,LE 运行时函数足够智能,可以“双模式”,因为相同的运行时函数可以在 USS 进程和非 USS 进程中工作。目标代码就是目标代码,(比如说)z/OS 文件打开和 UNIX 服务文件打开之间的区别无非是运行时调用 SVC 19(对于 z/OS OPEN)还是 BPX1OPN(对于 UNIX 服务文件)。这只是意味着,一旦您的代码被称为 USS 进程,您几乎可以按照您认为合适的方式混合 z/OS 和 USS 功能。
这也意味着没有理由不能在 PL/I 程序中使用诸如“libxyz.a”之类的东西,假设在 LE 级别没有不兼容性等等。让活页夹以您期望的方式解决所有问题可能是一个挑战,但如果您坚持下去,它应该会奏效。
PL/I 会有一些困难的事情(我很抱歉——我不是 PL/I 专家)。一个示例可能会调用类似于您的 libcurl 示例,其中库是 DLL 而不是静态存档。同样,这里的技巧可能是使用可以从 PL/I 调用的简短 C“存根”,并且该代码可以执行加载和调用 DLL 所需的魔法。否则,我想一旦你把所有的部分放在一起,你会发现这是一个非常简单的练习。