C low read function write function 64 bit equivalent?

I have code that uses the low and low I / O system calls read and write , as described on page 170 of the Kernighan and Ritchie C Programming Book. Function prototypes are

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

now two .c files that use these read and write are called by the larger fortran program to read and write large amounts of data.

C code is just this, without #include any type, having an underscore after the function name and following the link:

 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 program will do something like this

 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 guessed, this is great for nbyte values ​​less than 2 ^ 31. I need to read more than 2 GB of data, so I need nbyte to be a long integer and INTEGER * 8 in fortran.

Are there equivalent read64 and write64, for example, is lseek64 provided by unistd.h and features.h?

What is the best way to transcode this? Should I use fread and fwrite? is int fd from low level write the same as FILE *stream from fread() ?

My requirement is to pass a long integer of 8 bytes in order to have values ​​from 100 to 500 gigabytes or an integer having 12 digits, which is for nbyte

Am I getting something or losing using currently read and write , which is identified as a system call? "What does this mean?

+5
source share
2 answers

Edit: You cannot, at least not on Linux. read will never pass more than a 32-bit integer can contain.

From Linux files to read :

On Linux, read () (and similar system calls) will transmit no more than 0x7ffff000 (2,147,479,552), returning the number of bytes actually transferred. (This is true for both 32-bit and 64-bit systems.)

This is not a contraindication for POSIX, it is allowed by POSIX, but in the end it implements read behavior. According to Andrew Hanle , reading a 32GB file works great on Solaris. In this case, my old answer is still valid.

Old answer:

read can work fine with 64-bit files. It is defined in <unistd.h> as follows: -

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

You will need to configure your routines to work with size_t instead of int in order to properly support large files.

You should check SSIZE_MAX (the maximum value supported for count ) before using read with a large file and aborting it if it is small (or breaking it into smaller pieces). SSIZE_MAX is a specific implementation value.

+5
source

As seen from @Leandros, POSIX-compliant read() and write() implementations accept bytes of type size_t and return bytes of type ssize_t . These are probably definitions that actually apply to you, since the read() and write() functions are not defined by the C standard. However, the difference is not much difference because size_t should not be wider than int - actually it may be already.

You still have a big problem. Fortran code seems to assume that the C functions it calls will read / write the full specified number of bytes or otherwise fail, but POSIX read() and write() do not guarantee this when they succeed. Indeed, the other day there was a question that depended on the fact that these functions did not transmit more bytes at a time than could be represented by a 32-bit integer signed even on a 64-bit system with 64-bit [s]size_t .

You can kill both of these birds in one word by implementing the read_() and write_() functions in a loop, making consecutive calls to the base read() or write() function until the total number of bytes specified or an error has occurred.

0
source

Source: https://habr.com/ru/post/1247067/


All Articles