fwrite() 失败: EDC5024i:尝试关闭已在另一个线程中打开的文件



我正在提交一个 JCL 作业以在大型机中分配 VB 数据集。提交作业后,数据集创建成功。

然后我在大型机的omvs区域中运行一个java程序,以打开文件并将一些内容写入其中。当我尝试将数据写入文件时,出现以下错误。

//DD:SYS00011 : fwrite() 失败。EDC5024I 尝试关闭已被另一个线程打开的文件。errno=24 errno2=0xc0640021 last_op=0 errorCode=0x0.

JCL 提交以分配数据集:

//USERNAME JOB ABC,,NOTIFY=&SYSUID,CLASS=F,MSGLEVEL=(1,1),MSGCLASS=X 
//STEP1 EXEC PGM=IEFBR14 
//STEP DD DSN=ASD00T.SM.ULRL, 
// DISP=(NEW,CATLG,DELETE), 
// UNIT=SYSDA,SPACE=(1,(10,60),RLSE),AVGREC=M, 
// DCB=(RECFM=VB), 
// DSORG=PS

用于写入文件的代码:

zFileIn = new ZFile("//'ASD00T.INPUT.ULRL'", "rb,type=record,noseek");
if (zFileIn.getDsorg() != ZFile.DSORG_PS) {
throw new IllegalStateException("Input dataset must be DSORG=PS");
}
zFileOut = new ZFile("//'ASD00T.SM.ULRL'", "wb,type=record,noseek, recfm="+ zFileIn.getRecfm()+ ", lrecl="+ zFileIn.getLrecl());
long count = 0;
byte[] recBuf = new byte[zFileIn.getLrecl()];
int nRead;
while((nRead = zFileIn.read(recBuf)) >= 0) {
zFileOut.write(recBuf, 0, nRead);
count++;
}

问题的核心是你需要在完成编写后调用 ZFile.close() 方法。这样做将保证打开、写入和关闭都在同一线程下发生,您应该没问题。这是使用传统数据集而不是 USS 文件的副作用。

这样做的原因很复杂,但它与以下事实有关:在 z/OS 中,"传统"QSAM/BSAM/VSAM 数据集的行为与 UNIX 文件系统文件略有不同。

如果你正在写入一个UNIX文件(HFS,ZFS,NFS等)而不是传统的数据集,你正在做的事情将完美地工作......这是因为 USS 以不同的方式处理资源所有权 - 文件句柄在进程级别而不是线程级别拥有。当您打开 USS 文件时,该文件句柄可以被进程中的任何线程使用或关闭......这是由各种 UNIX 标准强制要求的,因此 z/OS 别无选择,只能以这种方式工作。

传统数据集有点不同。打开常规数据集时,定义打开文件的操作系统结构存储在锚定到打开文件的线程的内存中。文件句柄中有足够的信息可以从其他线程执行 I/O,但需要从打开文件的线程关闭文件。

现在,由于您的代码中似乎没有 close(),因此该文件将保持打开状态,直到您的 Java 线程结束。当 Java 线程结束时,系统运行时将获得控制权,以便清理您可能已分配的任何资源。它看到延迟打开的文件并尝试关闭它,但现在它没有在打开文件的线程下运行,因此您会看到失败。

通常,UNIX 文件和 z/OS 数据集的工作方式几乎完全相同,但此问题是细微差异之一。IBM 从标准合规性的角度来看侥幸逃脱了它,因为 z/OS 数据集不是任何标准的一部分,而且一般来说,它们可以互换使用的方式是一个很棒的功能。

顺便说一下,所有这些都在LE(语言环境)和C运行时参考的细则中详细说明。

相关内容

  • 没有找到相关文章

最新更新