如何一次写入()超过2G的数据
How to write() data more than 2G in a time
我已经定义了_LARGEFILE64_SOURCE
和_FILE_OFFSET_BITS 64
支持大于2G的open()文件。好像还可以吧
但是如果我尝试一次写入超过 2G 的数据(例如 64G),write() 将 return 一个比 64G 小得多的值(正好是 2147479552)。我估计write()一次只能写入小于2G的数据
这是我的代码:
#define _GNU_SOURCE
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <mmap.h>
#define SPACE_SIZE 68719476736
int main()
{
ssize_t err;
void* zeros;
int fd = open64("./test", O_CREAT|O_RDWR|O_LARGEFILE, 0644);
assert(fd != -1);
int zero_fd = open("/dev/zero", O_RDWR);
assert(zero_fd != -1);
zeros = mmap(NULL, SPACE_SIZE, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, zero_fd, 0);
assert(zeros != (void *)-1);
err = write(fd, zeros, SPACE_SIZE);
assert(err == SPACE_SIZE); // Received SIGABRT, err = 2147479552
munmap(zeros, SPACE_SIZE);
}
如何一次性写入()超过2G的数据?
补充信息:
readelf -h ./a.out
的结果。 a.out 是我的程序名
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x660
Start of program headers: 64 (bytes into file)
Start of section headers: 6672 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 28
确实如此,这一事实在 man write
:
中有详细记载
On Linux, write() (and similar system calls) will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actually transferred. (This is true on both 32-bit and 64-bit systems.)
因此,如果您使用 Linux,则无法在对 write()
的单次调用中写入 64GB。
但是,您可以创建一个看起来包含 64GB NUL 字节的文件,方法是寻找偏移量 64GB-1 并写入单个 NUL 字节。 (或者,正如 @o11c 在评论中指出的那样,您可以使用 ftruncate(fd, SPACE_SIZE);
。)其中任何一个都会创建一个稀疏文件,它实际上不会占用太多磁盘 space,但它会像它一样是 64GB 的 NUL。
我已经定义了_LARGEFILE64_SOURCE
和_FILE_OFFSET_BITS 64
支持大于2G的open()文件。好像还可以吧
但是如果我尝试一次写入超过 2G 的数据(例如 64G),write() 将 return 一个比 64G 小得多的值(正好是 2147479552)。我估计write()一次只能写入小于2G的数据
这是我的代码:
#define _GNU_SOURCE
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <mmap.h>
#define SPACE_SIZE 68719476736
int main()
{
ssize_t err;
void* zeros;
int fd = open64("./test", O_CREAT|O_RDWR|O_LARGEFILE, 0644);
assert(fd != -1);
int zero_fd = open("/dev/zero", O_RDWR);
assert(zero_fd != -1);
zeros = mmap(NULL, SPACE_SIZE, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, zero_fd, 0);
assert(zeros != (void *)-1);
err = write(fd, zeros, SPACE_SIZE);
assert(err == SPACE_SIZE); // Received SIGABRT, err = 2147479552
munmap(zeros, SPACE_SIZE);
}
如何一次性写入()超过2G的数据?
补充信息:
readelf -h ./a.out
的结果。 a.out 是我的程序名
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x660
Start of program headers: 64 (bytes into file)
Start of section headers: 6672 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 28
确实如此,这一事实在 man write
:
On Linux, write() (and similar system calls) will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actually transferred. (This is true on both 32-bit and 64-bit systems.)
因此,如果您使用 Linux,则无法在对 write()
的单次调用中写入 64GB。
但是,您可以创建一个看起来包含 64GB NUL 字节的文件,方法是寻找偏移量 64GB-1 并写入单个 NUL 字节。 (或者,正如 @o11c 在评论中指出的那样,您可以使用 ftruncate(fd, SPACE_SIZE);
。)其中任何一个都会创建一个稀疏文件,它实际上不会占用太多磁盘 space,但它会像它一样是 64GB 的 NUL。