C – archivo binario fwrite mayor a 4GB

Básicamente soy nuevo en C.

Tengo un Windows7 de 64 bits con 64 GB de RAM y 240 GB de SSD.

Trabajo con una placa de adquisición que almacena los datos adquiridos en 2 FIFO internos y luego pasa los datos a la RAM (por lo que potencialmente puedo adquirir, digamos, 60 GB de datos).

Lo que no puedo hacer es usar la función fwrite para escribir un archivo binario con un tamaño superior a 4 GB.

Aquí están mis variables:

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

Por lo tanto, al concentrarse en lo que sucede en FIFO # 1, el tablero realiza nacq adquisiciones de tamaño bufferLength12 y almacena todas las cosas en la RAM usando la memoria apuntada por 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)) 

Ahora quiero escribir los datos en 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; 

Cuando establezco nacq=2000 , el tamaño del archivo es 4’096’000 bytes. Si bash boost este valor, el progtwig se bloquea y si abandono la adquisición, obtengo un archivo binario con, por ejemplo, 1’960’000 bytes de dimensión.

¿Cómo puedo tener un archivo binario más grande?

En los comentarios, declara que su comstackdor es MSVC 2008 y que apunta a x64.

Sospecho que ha sido atrapado por un error de biblioteca en tiempo de ejecución. Por ejemplo, vea esta publicación: http://connect.microsoft.com/VisualStudio/feedback/details/755018/fwrite-hangs-with-large-size-count

Puede escribir más de 4 GB, pero no puede hacerlo con una sola llamada a fwrite . Tendrá que hacer varias llamadas que no pasen más de 4 GB a la vez.

En cualquier caso, seguramente sea un mejor enfoque para su problema. Su enfoque actual implica la asignación de un gran bloque de memoria. La solución le permitiría asignar un bloque de memoria más pequeño y, por lo tanto, generar menos demanda en la memoria del sistema.

La otra respuesta ha cubierto casi todo. Me gustaría señalar que no estás haciendo lo que crees que estás haciendo. Específicamente, recuerde que cada página en la RAM física puede ser respaldada por una página en el archivo de paginación (archivo de intercambio). Cuando escribe datos en la matriz en memoria, se accede a cada página que escribe solo una vez al escribir. Luego permanece inactivo durante bastante tiempo hasta que haya terminado con su adquisición y desee escribirlo. El sistema operativo, a sus espaldas, pagará los datos al disco mientras no los esté utilizando.

Lo que estás haciendo cuando lo “escribes” en un archivo es:

  1. Accedes a los datos al principio de tu búfer. Es probable que estos datos se envíen al disco en este momento ya que son muy antiguos. Puede que todavía esté en la RAM a pesar de estar en el disco al mismo tiempo, es probable que se trate de un sistema con batería, donde los sistemas operativos modernos están dertwigndo RAM obsoleta en el disco todo el tiempo para hacer que las hibernaciones sean más rápidas. Si ya no está en la RAM, el sistema operativo se encarga de la falla de la página y lee los datos por usted.

  2. Lo escribes en un archivo. Vuelve al disco, en una ubicación diferente.

Así que los datos hacen un viaje de ida y vuelta desde el disco a disco. Esto probablemente no es lo que quieres.

Puedes manejarlo de tres maneras.

  1. En lugar de usar el archivo de paginación de todo el sistema, deje que el sistema operativo use su archivo como un archivo de paginación. Lo haces mapeando tu archivo en memoria, y luego simplemente escribiéndolo en la memoria. Cuando cierra la asignación, se le garantiza que todas las páginas de memoria terminarán en su archivo. No hay viajes de ida y vuelta involucrados.

  2. Tiene dos hilos y un conjunto de buffers entrelazados. Un hilo llena los buffers, el otro los descarga en el disco. El enclavamiento evita que ambos hilos pisen los dedos de los pies de otros rsch. Esto le permite usar llamadas de locking que podrían ser más fáciles de manejar si no está familiarizado con winapi.

  3. Tener un hilo pero usar E / S sin locking. De esa manera, puede “escribir” en el disco sin esperar a que los datos lleguen allí. Hay bibliotecas por ahí para ayudarte con eso, impulso podría ser una buena opción.

Puede que me esté faltando algo, pero para mí la opción obvia después de que el hilo y la escritura se queden sin combustible es utilizar la función (originalmente Win32) creada en CreateFile, ReadFile, WriteFile y CloseHandle. Son mucho más capaces y supongo / supongo que las funciones f que está utilizando son envoltorios a su alrededor.

Dado que son más capaces, son algo más difíciles de aprender pero, bueno, el archivo de E / S no es una ciencia de cohetes. Si ha implementado código utilizando un conjunto de funciones de E / S, no perderá su forma de implementarlas.