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