Really slow disc image creation (iso 9660) in C

391 views Asked by At

As a fun project I thought I'd write a program to make iso files. As far as I can tell it works, but it reads only 4KB every 30 seconds. I used eject -x 11 to slow my cdrom drive to a reasonable speed. Without it the drive runs at full speed and kills the process pretty quickly. Any suggestions to make this faster/better will be much appreciated.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BUFFSIZE 4092

int main(int argc, char **argv)
{
    FILE *fp = fopen("/dev/cdrom", "r");
    FILE *file = fopen(strcat(argv[1], ".iso"), "w");

    printf("Copying...\n");

    while(!feof(fp))
    {
        char *line=(char *)malloc(sizeof(char) * BUFFSIZE);
        fgets(line, BUFFSIZE, fp);
        fprintf(file, "%s",line);

        free(line);
    }//end while

    fclose(fp);
    fclose(file);

    printf("Done!\n");

    return 0;
}//end main
5

There are 5 answers

0
Novikov On
  • Buffered IO is hardly appropriate in this scenario, neither is fgets which scans the input for a newline. Look into mmap.
  • Continuous buffer de/re-allocation slows you down.
  • Fprintf is not right for writing binary data. It's also slow.
0
Danish On

I am no C guru, but sounds like you need to implement some form of buffered readers and writers of data to see performance improvements.

0
pmg On

Move the malloc and free outside the loop.

1
wnoise On

fgets() handles text and is line oriented, and wastes time looking for newlines. Furthermore, it and fprintf() don't handle NUL bytes, and can get very confused by them. You want to use binary IO, i.e. fread() and fwrite(). There is also no need to continually free() and reallocate your buffer.

If you want to use Unix IO primitives rather than the C wrappers, you could use read() and write() or mmap() instead.

0
Matteo Italia On

First of all, I wouldn't go with formatted input (fgets & text mode), but with raw binary input (fopen with the b flag, fread and fwrite for writing). This way stdio doesn't need to perform the substitutions needed for the text mode (if needed on your platform), and you have a series of fixed-size reads that should perform better than fgets' waiting for the \n.

Then, I would get rid of that dynamic memory allocation; the continuous allocation/deallocation is probably killing the performance of your application. Just allocate once for all a static buffer on the stack (e.g. 8192 bytes) and use it all the time.