代码如下:
fopen("DD:LOGLIBY(L1234567)", "w");JCL喜欢:
//LOGTEST EXEC PGM=LOGTEST
//LOGLIBY DD DSN=MYUSER.LOG.LIBY,DISP=SHR我可以创建PDS(E)成员,同时浏览PDS(E)以查看现有成员,正如DISP=SHR所期望的那样。
如果相反,我编码:
fopen("//'MYUSER.LOG.LIBY(L1234567)'", "w");如果我当时正在浏览PDS(E),则fopen失败,或者当我打开文件时浏览PDS(E)失败。换句话说,不存在DISP=SHR。根据fopen()文档,在使用"r“等文件模式时,DISP=SHR是默认的,而不是"w”。
如何在第二个示例中提供DISP=SHR?
发布于 2020-06-05 15:51:54
有两种可能性。
对于任何不熟悉分区数据集(即PDS或PDS/E)内部结构的人,这些数据集逻辑上分为两个部分:一个包含指向所有单个成员的指针的“目录”和一个包含单个成员的实际记录的“数据”区域:
PDS: <DIRECTORY BLOCKS>
<MEMBER1>: ADDRESS OF DATA FOR MEMBER1 (xxx)
<MEMBER2>: ADDRESS OF DATA FOR MEMBER2 (yyy)
...
<DIRECTORY FREESPACE)
...
<EOF - END OF THE PDS DIRECTORY>
<DATA PORTION>
+xxx = DATA FOR MEMBER1
...
<EOF - END OF MEMBER1>
+yyy = DATA FOR MEMBER2
...
<EOF - END OF MEMBER2>
...
FREE SPACE (ALLOCATED, BUT UNUSED)
...
END OF PDS 在接下来的几段中,请记住,您可以打开整个PDS/PDSE,这使您能够读取/写入任何您喜欢的成员,或者您可以分配和打开单个成员,这将像任何其他顺序文件一样被处理。
首先,如果您实际上要像在问题中显示的那样编写DD语句,那么您可能只需要将open从fopen(dsn,...)更改为fopen(dd:ddname,...)。如果您在UNIX下运行,或者您所做的事情导致您的进程在不同的地址空间中运行(例如fork()),那么这可能不起作用,但可能值得一试。如果使用显示的JCL执行此操作,挑战将是管理PDS/E目录--在创建/更新新成员时,需要发出自己的"STOW“,因为JCL分配的是整个数据集,而不仅仅是单个成员。顺序如下:
打开DD以便输出。updated).
)。
如果还需要读取成员,则需要发出FIND (或BLDL/POINT --在C中可以是FIND())来指向正确的成员,然后读取成员。我肯定这听起来很麻烦,但是这种方法的优点是您可以分配/打开文件一次,并且可以处理任意多个成员。
第二个解决方法可能是自己动态分配文件,然后使用DD:ddname syntax...if打开它--您很少访问该文件,这可能更容易编写代码。动态分配的血淋淋的细节在这里充分描述:https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ieaa800/reqsvc.htm。
调用动态分配有几种方法:您可以编写一个小型汇编程序,可以使用z/可调用服务,或者可以使用C运行时"dynalloc()“或"svc99()”函数。dynalloc()函数易于使用,但它只公开了动态分配的子集,do...svc99()使用起来更麻烦,但它公开了更多的功能。
不管您怎么做,动态分配都采用“文本单元”,这些“文本单元”与您在JCL语句中找到的参数大致对应。您所描述的内容听起来像是只需要传递DSN和DISP文本单元,或者是DDNAME (您可以传递您自己的DDNAME,或者让系统为您生成一个)。
C运行时函数使这一切变得简单,但是要注意有一些奇怪之处,比如需要将参数压缩到它们的最大长度。例如,DSN需要44个字符,并在右边填充空格--而不是C样式的空尾字符串。
下面是一个小的代码片段,作为一个例子:
#include <dynit.h>
. . .
int allocate(ddn, dsn, mem)
{
__dyn_t ip; // Parameters to dynalloc()
. . .
// Prepare the parameters to dynalloc()
dyninit(&ip); // Initialize the parameters
ip.__ddname = ddn; // 8-char blank-padded
ip.__dsname = dsn; // 44-char blank-padded
ip.__status = __DISP_SHR; // DISP=(SHR)
ip.__normdisp = __DISP_KEEP; // DISP=(...,KEEP)
ip.__misc_flags = __CLOSE; // FREE=CLOSE
if (*mem) // Optional PDS, PDS/E member
ip.__member = mem; // 8-char blank-padded
// Now we can call dynalloc()...
if (dynalloc(&ip)) // 0: Success, else error
{
// On error, the errcode/infocode explain why - values
// are detailed in z/OS Authorized Services Reference
printf("SVC99: Can't allocate %s - RC 0x%x, Info 0x%x\n",
dsn, ip.__errcode, ip.__infocode);
return FALSE;
}
// If dynalloc works, you can open the file with fopen("DD:ddname",...)
}不要忘记,当您完成文件,您通常需要释放它。上面的代码片段使用"FREE=CLOSE“--这意味着当文件关闭时,z/OS将自动释放只打开一次并处理数据集一次的allocation...if,这是一种方便的方法。如果您需要反复打开和关闭文件,则不会使用FREE=CLOSE,而是在完成处理后第二次调用动态分配,并希望释放该文件。
如果您需要并发访问多个文件,请注意,您将需要生成多个唯一的DDNAME。您可以在自己的代码中这样做,也可以使用动态分配的形式自动构建和返回可用的DDNAME (表单"SYSnnnnn")。
另外,不要忘记在某些情况下更新DISP=SHR下的数据集可能是危险的,特别是如果所涉及的数据集可能是常规的PDS和PDS/E。最大的危险是两个应用程序打开dataset以便输出concurrently...both将数据写入相同的位置,其结果可能是损坏的PDS目录。
UNIX环境中还有其他一些奇怪之处,特别是如果您使用fork()或exec()并期望文件句柄在子进程中工作,因为分配通常与特定的z/OS地址空间相关联。spawn()之类的服务可以让子进程在相同的地址空间中运行,因此这是一种可能性。
https://stackoverflow.com/questions/62080677
复制相似问题