La projection


Un exemple

Le programme suivant réalise une copie de fichier par projection d'un fichier en mémoire. Il est intéressant de comparer les temps d'exécutions entre la version avec projection et sans.

/*
 * A fast copy utility
 *
 * Author: Jean-Baptiste Yunès
 * Date  : May 2000
 */

#if (_POSIX_C_SOURCE > 2)
#include <sys/mman.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc,char *argv[]) {
  int src, dst;
#if (_POSIX_C_SOURCE > 2)
  void *src_addr;
#else
#define BUFLEN 1000
  unsigned char buffer[1000];
  ssize_t nc;
#endif
  struct stat stat_buf;
  
  if (argc!=3) {
    fprintf(stderr,"Usage: %s <src> <dst>\n",argv[0]);
    exit(EXIT_FAILURE);
  }
  if ( (src=open(argv[1],O_RDONLY)) < 0) {
    fprintf(stderr,"%s: cannot open %s for reading\n",argv[0],argv[1]);
    exit(EXIT_FAILURE);
  }
  if ( (dst=open(argv[2],O_CREAT|O_RDWR|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0 ) {
    fprintf(stderr,"%s: cannot open %s for writing\n",argv[0],argv[2]);
    close(src);
    exit(EXIT_FAILURE);
  }
#if (_POSIX_C_SOURCE > 2)
  if ( fstat(src,&stat_buf) == -1 ) {
    fprintf(stderr,"%s: cannot stat %s\n",argv[0],argv[1]);
    close(dst);
    close(src);
    exit(EXIT_FAILURE);
  }
  if ( ftruncate(dst,stat_buf.st_size) < 0 ) {
    fprintf(stderr,"%s: unable to write %ld bytes in %s\n",argv[0],
	    stat_buf.st_size,argv[2]);
    close(dst);
    close(src);
    exit(EXIT_FAILURE);
  }
  /* Map the source file inside the address space */
  src_addr = mmap(NULL,stat_buf.st_size,PROT_READ,MAP_NORESERVE|MAP_PRIVATE,src,0);
  if ( src_addr==(void *)MAP_FAILED ) {
    fprintf(stderr,"%s: problem mapping file %s\n",argv[0],argv[1]);
    close(dst);
    close(src);
    exit(EXIT_FAILURE);
  }
  /* Write data to the destination file */
  if ( write(dst,src_addr,stat_buf.st_size)!=stat_buf.st_size ) {
    fprintf(stderr,"%s: problem writing %s\n",argv[0],argv[2]);
    munmap(src_addr,stat_buf.st_size);
    close(dst);
    close(src);
    exit(EXIT_FAILURE);
  }
  munmap(src_addr,stat_buf.st_size);
#else
  do {
    if ( (nc=read(src,buffer,BUFLEN)) < 0 ) {
      fprintf(stderr,"%s: problem reading %s\n",argv[0],argv[1]);
      close(dst);
      close(src);
      exit(EXIT_FAILURE);
    }
    if ( write(dst,buffer,nc)!= nc ) {
      fprintf(stderr,"%s: problem writing %s\n",argv[0],argv[1]);
      close(dst);
      close(dst);
      exit(EXIT_FAILURE);
    }
  } while ( nc );
#endif
  close(dst);
  close(src);
  exit(EXIT_SUCCESS);
}