Как записать () данные более 2G за раз - PullRequest
0 голосов
/ 12 мая 2018

Я уже определил _LARGEFILE64_SOURCE и _FILE_OFFSET_BITS 64 для поддержки файла open () более 2G. Кажется, все в порядке.

Но если я попытаюсь записать () данные более 2G за раз (например, 64G), write () вернет значение, значительно меньшее 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

1 Ответ

0 голосов
/ 12 мая 2018

Действительно, и этот факт хорошо задокументирован в man write:

В Linux функция write () (и аналогичные системные вызовы) будет передавать не более 0x7ffff000 (2 147 479 552) байта, возвращая числобайтов фактически переданы.(Это верно как для 32-разрядных, так и для 64-разрядных систем.)

Так что, если вы используете Linux, невозможно записать 64 ГБ за один вызов write().

Однако вы можете создать файл, который содержит 64 ГБ байтов NUL, пытаясь сместить 64 ГБ-1 и записав один байт NUL.(Или, как указывает @ o11c в комментарии, вы можете использовать ftruncate(fd, SPACE_SIZE);.) Любой из них создаст разреженный файл, который на самом деле не будет занимать много места на диске, но будет действовать так, как если бы это были 64 ГБ NUL.

...