C – битный файл fwrite размером более 4 ГБ

Я в основном новичок в C.

У меня 64-разрядная Windows7 с 64 ГБ оперативной памяти и 240 ГБ SSD.

Я работаю с доской сбора, которая хранит полученные данные во 2 внутренних FIFO, а затем передает данные в ОЗУ (так что я могу потенциально получить, скажем, 60 ГБ данных).

То, что я не могу сделать, это использовать функцию fwrite для записи двоичного файла размером более 4 ГБ.

Вот мои переменные:

 static UINT64 *rbuffer12 = NULL; static UINT64 *rbuffer34 = NULL; FILE *fd_raw, *fd_raw2; UINT64 nacq = 2000; ICS1555_ULONG_T bufferLength12, bufferLength34; 

Итак, сосредоточив внимание на том, что происходит в FIFO # 1, плата делает nacq приобретения размера bufferLength12 и хранит все bufferLength12 в ОЗУ с использованием памяти, указанной rbuffer12 .

 bufferLength12 = 524288; acq_length = 524288 / (channels_number * 2 * 4); nBytes = bufferLength12 * 4; rbuffer12 = (UINT64 *) malloc(nacq*nBytes); memset(rbuffer12, 0, nacq*nBytes); for (i = 0; i < 4*nacq; i++) ReadF(h, 0, (UINT64 *) (rbuffer12 + i * bufferLength12/8), nBytes/4, NULL, 0)) 

Теперь я хочу записать данные в File12.bin .

 fd_raw=fopen("File12.bin","wb") fwrite((UINT64 *) rbuffer12,8,(nacq * 4 * channels_number * acq_length) ,fd_raw); fclose(fd_raw); fd_raw=NULL; 

Когда я устанавливаю nacq=2000 , размер файла составляет 4’096’000 байт. Если я попытаюсь увеличить это значение, программа зависает, и если я уйду с приобретения, я получаю двоичный файл, например, размером 1’960’000 байтов.

Как я могу получить более крупный двоичный файл?

Вы указываете в комментариях, что ваш компилятор MSVC 2008 и что вы нацеливаете x64.

Я подозреваю, что вы были пойманы ошибкой библиотеки времени выполнения. Например, см. Это сообщение: http://connect.microsoft.com/VisualStudio/feedback/details/755018/fwrite-hangs-with-large-size-count

Вы можете написать более 4 ГБ, но вы не можете сделать это с помощью одного вызова fwrite . Вам необходимо сделать несколько вызовов, проходящих не более 4 ГБ за раз.

В любом случае это, безусловно, лучший подход к вашей проблеме. Ваш текущий подход предполагает выделение одного огромного блока памяти. Работа вокруг позволит вам выделить меньший блок памяти и, таким образом, уменьшить нагрузку на память системы.

Другой ответ покрыл почти все. Я хотел бы указать, что вы не делаете то, что думаете, что делаете. В частности, помните, что каждая страница в физической RAM может поддерживаться страницей в файле подкачки (файл подкачки). Когда вы записываете данные в массив в памяти, каждая страница, которую вы пишете, получает только один раз при записи. Затем он долгое время не используется, пока вы не закончите свое приобретение и не захотите его написать. Операционная система за вашей спиной выводит данные на диск, пока вы их не используете.

То, что вы делаете, когда вы «пишете» его в файл:

  1. Вы получаете доступ к данным в начале вашего буфера. На данный момент эти данные, вероятно, выгружаются на диск, так как они очень старые. Он все еще может находиться в ОЗУ, несмотря на то, что он одновременно находится на диске – это, скорее всего, в системе с батарейным питанием, где современные операционные системы все время разливают устаревшую RAM на диск, чтобы ускорить спячку. Если он больше не находится в ОЗУ, операционная система обрабатывает ошибку страницы и считывает данные для вас.

  2. Вы пишете это в файл. Он возвращается на диск в другом месте.

Таким образом, данные выполняют обратный переход с диска на диск. Это, вероятно, не то, что вы хотите.

Вы можете справиться с ним тремя способами.

  1. Вместо использования общесистемного файла подкачки, пусть ОС использует ваш файл в качестве файла подкачки. Вы делаете это путем сопоставления памяти с вашим файлом, а затем просто записываете в память. Когда вы закрываете сопоставление, вам гарантируется, что все страницы памяти попадают в ваш файл. Никаких побочных действий.

  2. Имеют два streamа и набор блокированных буферов. Один stream заполняет буферы, другой stream выгружает их на диск. Блокировка препятствует тому, чтобы оба streamа наступали на пальцы rsch other. Это позволяет использовать блокирующие вызовы, с которыми может быть легче справиться, если вы не слишком хорошо знакомы с winapi.

  3. Имейте один stream, но используйте неблокирующий ввод-вывод. Таким образом, вы можете «написать» на диск, не дожидаясь, когда данные действительно туда попадут. Там есть библиотеки, которые помогут вам в этом, повышение может быть одним хорошим выбором.

Возможно, мне что-то не хватает, но для меня очевидным выбором после того, как fread и fwrite иссякнут из газа, следует использовать функцию (первоначально Win32) set CreateFile, ReadFile, WriteFile и CloseHandle. Они намного более способны, и я предполагаю / предполагаю, что используемые вами f-функции являются обертками вокруг них.

Поскольку они более способны, их несколько труднее изучить, но эй, файл-ввод-вывод – это не ракетостроение. Если вы внедрили код с помощью одного набора функций ввода-вывода, вы не потеряете свой путь реализации.