首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在fopen上使用DISP=SHR

如何在fopen上使用DISP=SHR
EN

Stack Overflow用户
提问于 2020-05-29 07:19:04
回答 1查看 333关注 0票数 1

代码如下:

代码语言:javascript
复制
fopen("DD:LOGLIBY(L1234567)", "w");

JCL喜欢:

代码语言:javascript
复制
//LOGTEST  EXEC PGM=LOGTEST
//LOGLIBY  DD   DSN=MYUSER.LOG.LIBY,DISP=SHR

我可以创建PDS(E)成员,同时浏览PDS(E)以查看现有成员,正如DISP=SHR所期望的那样。

如果相反,我编码:

代码语言:javascript
复制
fopen("//'MYUSER.LOG.LIBY(L1234567)'", "w");

如果我当时正在浏览PDS(E),则fopen失败,或者当我打开文件时浏览PDS(E)失败。换句话说,不存在DISP=SHR。根据fopen()文档,在使用"r“等文件模式时,DISP=SHR是默认的,而不是"w”。

如何在第二个示例中提供DISP=SHR

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-05 15:51:54

有两种可能性。

对于任何不熟悉分区数据集(即PDS或PDS/E)内部结构的人,这些数据集逻辑上分为两个部分:一个包含指向所有单个成员的指针的“目录”和一个包含单个成员的实际记录的“数据”区域:

代码语言:javascript
复制
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).

  • Close

  • 写入您的数据。

  • 用新的成员信息更新PDS或PDS/E目录(这是STOW函数出现的地方-它更新PDS/PDSE的目录以反映您创建的成员或

  • 文件

)。

如果还需要读取成员,则需要发出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样式的空尾字符串。

下面是一个小的代码片段,作为一个例子:

代码语言:javascript
复制
#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()之类的服务可以让子进程在相同的地址空间中运行,因此这是一种可能性。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62080677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档