On Wed, 22 Jun 2005, Eli Billauer wrote:

Insights, anybody?

Reliable high speed continuous writes on a multitasking system like linux are not possible. The next time there is network load or a daemon wakes up your task will be scheduled out. You can do it with RTLinux or VmWare or QNX. The closest you can get on linux is to use a SCHED_RR scheduled process with high priority as root and poll or select on the relevant file descriptors, all set to unbuffered mode (O_NDELAY), and lock the buffer and the program in memory. If you have to maintain the speed you must buy an AV disk which is specifically rated not to recalibrate from time to time. Look at the source code of cdrecord f.ex. for clues. It uses all the methods I have enumerated, plus mmap. It is possible to rise the priority of a single task so high that the system will be unusable for anything else using these methods (it appears frozen excepting the high priority task). You must find your tradeoff. Tivo etc. boxes do this (they don't do much besides recording and playing video so it's ok).

Peter
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

char junkdata[32768];

int main(int argc, char **argv) {
  FILE *f;

  struct timeval now, sleeptime;
  struct timezone junk;
  long prev_sec, prev_usec, deltat;
  int i;

  if (argc!=2) {
    fprintf(stderr, "Usage: %s output-filename\n", argv[0]);
    return 1;
  }

  f = fopen (argv[1], "wb");

  if (f==NULL) {
    fprintf(stderr, "Failed to open output file %s\n", argv[1]);
    return 1;
  }

  if (gettimeofday(&now, &junk) != 0) {
    fprintf(stderr, "gettimeofday() failed!\n");
    return 1;
  }

  prev_sec = now.tv_sec; prev_usec = now.tv_usec;

  for (i=0; i<2047*32; i++) { // Almost 2 GB
    
    // Time to sleep between writes. Check this program's output values
    // to see what you actually got as typical values. They may be
    // significantly longer than requested due to context switch overhead
    // when the desired time is very short.
    sleeptime.tv_sec = 0; 
    sleeptime.tv_usec = 100; // Yeah, right. The real value will be much longer
    
    // Next line should be commented out for full-speed
    // select(0, NULL, NULL, NULL, &sleeptime);
    
    if (fwrite (junkdata, 1, sizeof(junkdata), f) != sizeof(junkdata)) {
      fprintf(stderr, "Data write failed!\n");
      return 1;
    }
    
    if (gettimeofday(&now, &junk) != 0) {
      fprintf(stderr, "gettimeofday() failed!\n");
      return 1;
    }
  
    deltat = now.tv_sec - prev_sec;
    deltat = deltat * 1000000;
    deltat +=  now.tv_usec - prev_usec;

    prev_sec = now.tv_sec; prev_usec = now.tv_usec;

    printf("%ld\n", deltat);

  }
  
  fclose(f);
  return 0;
}

Reply via email to