我有一些代码使用低级别的i / o read
和write
系统调用,如C编程语言书籍Kernighan和Ritchie的第170页所述。
函数原型是这个
int n_read = read ( int fd, char *buf, int n )
int n_read = write ( int fd, char *buf, int n )
现在使用这些read
和write
的两个.c文件被更大的基于fortran的程序调用,以读取和写入大量数据。
C代码就是这样,没有任何类型的#include
,在函数名后跟下划线并通过引用传递:
int read_ ( int *descriptor, char *buffer, int *nbyte )
{
return ( read( *descriptor, buffer, *nbyte ) );
}
int write_ ( int *descriptor, char *buffer, int *nbyte )
{
return ( write( *descriptor, buffer, *nbyte ) );
}
而较大的基于fortran的程序会做这样的事情
INTEGER nbyte
COMPLEX*16 matrix(*)
INTEGER READ, WRITE
EXTERNAL READ, WRITE
status = READ( fd, matrix, nbyte )
if ( status .eq. -1 ) then
CALL ERROR('C call read failure')
stop
endif
正如您可能已经猜到的,这适用于 nbyte 小于2 ^ 31的值。我需要读取超过2 GB的数据,因此我需要 nbyte 在fortran中成为长整数和 INTEGER * 8 。
有没有等效的read64和write64,就像unistd.h和features.h提供的lseek64一样?
重新编码的最佳方法是什么?
我应该使用fread和fwrite吗?
来自int fd
的{{1}}与write
的{{1}}相同?
我的要求是能够传递一个8字节的长整数,以允许最大100到500千兆字节的值或一个12位数的整数,这是 nbyte 的值
目前使用FILE *stream
和fread()
标识为“系统调用”,我获得了什么或输了?这是什么意思?
答案 0 :(得分:5)
编辑:您不能,至少不在Linux上。 <{1}}永远不会传输超过32位整数可以容纳的内容。
从read
上的Linux联机帮助页:
在Linux上,read()(以及类似的系统调用)最多将传输 0x7ffff000(2,147,479,552)个字节,返回字节数 实际转移。 (32位和64位都是如此 系统。)
这不是POSIX的约束,它是POSIX所允许的,但最终它的实现定义了read
的行为方式。正如Andrew Hanle报告的那样,读取32GB文件在Solaris上运行正常。在这种情况下,我的旧答案仍然有效。
旧答案:
read
可以正常使用64位文件。它在read
中的定义如下: -
<unistd.h>
您必须调整例程才能使用ssize_t read(int fd, void *buf, size_t count);
代替size_t
,以便正确支持大文件。
在将int
与大文件一起使用之前,您应该检查SSIZE_MAX
(count
支持的最大值),如果它是小的,则应中止(或拆分为较小的块)。 read
是实现定义的值。
答案 1 :(得分:0)
正如@Leandros所观察到的,符合POSIX的read()
和write()
实现接受size_t
类型的字节计数,并返回类型为ssize_t
的字节计数。这些可能是实际适用于您的定义,因为C标准未指定read()
和write()
函数。然而,这并没有太大区别,因为size_t
不需要比int
更宽 - 事实上,它可以更窄。
你无论如何都有更大的问题。 Fortran代码似乎假设它正在调用的C函数将读取/写入指定的完整字节数,否则会失败,但POSIX read()
和write()
在成功时无法保证这样做。实际上,前几天存在一个问题,这个问题取决于这样的事实:这些函数一次不能传输更多的字节,而不是一个有符号的32位整数,即使在64位系统上也是如此。位[s]size_t
。
通过将read_()
和write_()
函数实现到循环,执行对基础read()
的连续调用,可以一举杀死这两只鸟write()
函数,直到传输完整数量的指定字节或发生错误。