简体   繁体   English

C低级读写功能等效于64位吗?

[英]C low level read write functions 64-bit equivalent?

I have some code that uses the low level i/o read and write system calls, as described on page 170 of the C programming language book Kernighan and Ritchie. 我有一个使用水平低一些代码I / O readwrite系统调用,如C语言编程的书Kernighan和里奇的170页上介绍。 The function prototypes are this 功能原型是这个

int n_read = read  ( int fd, char *buf, int n )
int n_read = write ( int fd, char *buf, int n )

now the two .c file that uses these read and write are called by a larger fortran based program to read and write lots of data. 现在,一个较大的基于fortran的程序调用了使用这些readwrite的两个.c文件来读取和写入大量数据。

the C code is simply this, with no #include of any kind, having the underscore after the function name and passing by reference: 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 ) );
}

and the larger fortran based program will do something like this 而较大的基于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

As you may have already guessed, this works fine for nbyte values less than 2^31. 您可能已经猜到,这对于小于2 ^ 31的nbyte值可以正常工作。 I have a need to read more than 2 GB of data, so i need nbyte to be a long integer and INTEGER*8 in fortran. 我需要读取2 GB以上的数据,因此我需要nbyte是一个长整数 ,在fortran中为INTEGER * 8

Is there an equivalent read64 and write64, like there is an lseek64 provided by unistd.h and features.h ? 是否有等效的read64和write64,如unistd.h和features.h提供的lseek64?

what is the best way to recode this? 重新编码的最佳方法是什么? should i use fread and fwrite ? 我应该使用fread和fwrite吗? is the int fd from the low level write the same as FILE *stream from fread() ? int fd从低电平write相同FILE *streamfread()

my requirement is being able to pass a long integer of 8 bytes to allow for values up to 100 to 500 gigabytes or an integer having 12 digits, which is all for the value of nbyte 我的要求是能够传递8个字节的长整数,以允许最大100到500 GB的值或具有12位数字的整数,所有这些都是nbyte的值

Am i gaining anything or losing out by currently using read and write which is identified as a "system call" ? 难道我得到什么或者目前使用输给了readwrite标识为“系统呼叫”? What does this mean? 这是什么意思?

Edit: You can't, at least not on Linux. 编辑:您不能,至少不能在Linux上。 read will never transfer more than what a 32-bit integer can hold. read将永远不会传输超过32位整数可以容纳的内容。

From the manpages of Linux on read : 从Linux的联机手册中read

On Linux, read() (and similar system calls) will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actually transferred. 在Linux上,read()(和类似的系统调用)将最多传输0x7ffff000(2,147,479,552)字节,并返回实际传输的字节数。 (This is true on both 32-bit and 64-bit systems.) (在32位和64位系统上都是如此。)

This is not a contraint of POSIX, it's allowed by POSIX, but in the end it's implementation defined how read behaves. 这不是POSIX的约束,它是POSIX允许的,但是最后它的实现定义了read行为。 As Andrew Hanle reports, reading a 32GB file works just fine on Solaris. 正如安德鲁·汉勒(Andrew Hanle)报告的那样,在Solaris上读取32GB文件效果很好。 In this case, my old answer is still valid. 在这种情况下,我的旧答案仍然有效。

Old Answer: 旧答案:

read can work with 64-bit files just fine. read可以与64位文件配合使用。 It's defined in <unistd.h> as the following:- 它在<unistd.h>定义如下:-

ssize_t read(int fd, void *buf, size_t count);

You would have to adjust your routines to work with size_t instead of int , to properly support big files. 您必须调整例程以使用size_t而不是int ,才能正确支持大文件。

You should check SSIZE_MAX (the maximum value supported for count ), before using read with a big file, and abort if it's to small (or split into smaller chunks). 在对大文件使用read之前,应检查SSIZE_MAX (为count支持的最大值),如果文件较小(或拆分为较小的块),则中止。 SSIZE_MAX is an implementation defined value. SSIZE_MAX是实现定义的值。

As @Leandros observed, POSIX-conforming implementations of read() and write() accept byte counts of type size_t , and return byte counts of type ssize_t . 正如@Leandros所观察到的,符合POSIX的read()write()接受size_t类型的字节计数,并返回ssize_t类型的字节计数。 These are probably the definitions that actually apply to you, as the read() and write() functions are not specified by the C standard. 这些可能是实际上适用于您的定义,因为C标准未指定read()write()函数。 That's a distinction without much difference, however, because size_t is not required to be wider than int -- in fact, it can be narrower. 但是,这是一个区别,没有太大区别,因为size_t不需要比int宽-实际上,它可以更窄。

You anyway have a bigger problem. 无论如何,您有更大的问题。 The Fortran code seems to assume that the C functions it is calling will read / write the full specified number of bytes or else fail, but POSIX read() and write() are not guaranteed to do that when they succeed. Fortran代码似乎假设它正在调用的C函数将读取/写入指定的完整字节数,否则将失败,但是POSIX read()write()不能保证在它们成功时就这样做。 Indeed, there was a question around here the other day that hinged on the fact that these functions did not transfer more bytes at a time than can be represented by a signed, 32-bit integer, even on a 64-bit system with 64-bit [s]size_t . 确实,前几天在这里存在一个问题,该问题取决于以下事实:即使在具有64位元的64位系统上,这些函数一次传输的字节数也不会超过有符号的32位整数所表示的字节数。 [s]size_t位。

You can kill both of these birds with one stone by implementing the read_() and write_() functions to loop , performing successive calls to the underlying read() or write() function, until the full number of specified bytes is transferred or an error occurs. 您可以通过实现read_()write_()函数循环执行,对基础read()write()函数进行连续调用,直到将指定字节的全部数量传输或发生错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM