Copia con System Calls write/read

27 Maggio 2011

NB: a parità di grandezza di file copiato, questo utilizzo delle system calls è circa il 40% più lento dell’utilizzo della chiamata sendfile del programma Fast Copy

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>

#include <errno.h>
#include <sys/time.h>
#include <sys/stat.h>

int main (int argc, char** argv)

{
  int src;               /* file descriptor for source file */
  int dest;              /* file descriptor for destination file */

  struct stat stat_buf;  /* hold information about input file */
  int rc;                /* return code from sendfile */

  int loop; /* counts how many times the file has been copied */
  double sumoftimes=0.0;
  char buffer[BUFSIZ];

  struct timeval tv;
  struct timeval start_tv;

  /* check for two command line arguments */
  if (argc != 4) {

    fprintf(stderr, "usage: %s <source> <destination> <repetitions>\n", argv[0]);

    exit(1);
  }

  /* copy file using write */
  for(loop=0; loop<atoi(argv[3]); loop++)

  {
    /* check that source file exists and can be opened */
    src = open(argv[1], O_RDONLY);

    if (src == -1) {
      fprintf(stderr, "unable to open '%s': %s\n", argv[1], strerror(errno));

      exit(1);
    }
    /* open destination file */
    dest = open(argv[2], O_WRONLY|O_CREAT, stat_buf.st_mode);

    if (dest == -1) {
      fprintf(stderr, "unable to open '%s': %s\n", argv[2], strerror(errno));

      exit(1);
    }
	gettimeofday(&start_tv, NULL);

	while((rc=read(src, buffer, BUFSIZ)) > 0 )

	{
	  write(dest, buffer, rc);
	}

    gettimeofday(&tv, NULL);
    sumoftimes += (tv.tv_sec - start_tv.tv_sec) + (tv.tv_usec - start_tv.tv_usec) / 1000000.0;

    /* print walkthrough */
    fprintf(stdout, "[%d/%s] %f %f %f\n", loop, argv[3], tv.tv_sec+(tv.tv_usec/ 1000000.0), start_tv.tv_sec+(start_tv.tv_usec / 1000000.0), sumoftimes);

	close(dest);
	close(src);
	unlink(dest);

	unlink(src);
  }
  fprintf(stdout, "\nTempi di esecuzione [totale, prove, media]: %f %s %f secondi\n", sumoftimes, argv[3], sumoftimes/atoi(argv[3]));

  return 0;
}

syntax highlighted by Code2HTML, v. 0.9.1

syntax highlighted by Code2HTML, v. 0.9.1

Fast copy in linux with zero-copy

27 Maggio 2011
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <fcntl.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/sendfile.h>
#include <sys/stat.h>

int main (int argc, char** argv)

{
  int src;               /* file descriptor for source file */
  int dest;              /* file descriptor for destination file */

  struct stat stat_buf;  /* hold information about input file */
  off64_t offset = 0;    /* byte offset used by sendfile */

  int rc;                /* return code from sendfile */
  int loop; 			 /* counts how many times the file has been copied */
  double sumoftimes=0.0;

  struct timeval tv;
  struct timeval start_tv;

  /* check for two command line arguments */
  if (argc != 4) {

    fprintf(stderr, "usage: %s <source> <destination> <repetitions>\n", argv[0]);

    exit(1);
  }

  /* copy file using write */
  for(loop=0; loop<atoi(argv[3]); loop++)

  {
    /* check that source file exists and can be opened */
    src = open(argv[1], O_RDONLY);

    if (src == -1) {
      fprintf(stderr, "unable to open '%s': %s\n", argv[1], strerror(errno));

      exit(1);
    }
    /* get size and permissions of the source file */
    fstat(src, &stat_buf);

    /* open destination file */
    dest = open(argv[2], O_WRONLY|O_CREAT|O_CLOEXEC, stat_buf.st_mode);

    if (dest == -1) {
      fprintf(stderr, "unable to open '%s': %s\n", argv[2], strerror(errno));

      exit(1);
    }
    gettimeofday(&start_tv, NULL);

      rc = sendfile64(dest, src, &offset, stat_buf.st_size);

    gettimeofday(&tv, NULL);
    if (rc == -1) {

      fprintf(stderr, "error from sendfile: %s\n", strerror(errno));
      exit(1);

    }
    sumoftimes += (tv.tv_sec - start_tv.tv_sec) + (tv.tv_usec - start_tv.tv_usec) / 1000000.0;

    /* print walkthrough */
    fprintf(stdout, "[%d/%s] %f %f %f\n", loop+1, argv[3], tv.tv_sec+(tv.tv_usec/ 1000000.0), start_tv.tv_sec+(start_tv.tv_usec / 1000000.0), sumoftimes);

    close(dest);
    close(src);
    unlink(src);

    unlink(dest);
    offset=0;
  }

  fprintf(stdout, "\nTempi di esecuzione [totale, prove, media]: %f %s %f secondi\n", sumoftimes, argv[3], sumoftimes/atoi(argv[3]));

  return 0;
}

syntax highlighted by Code2HTML, v. 0.9.1

adjList.c

26 Novembre 2008
#include <stdio.h>
#include <stdlib.h>

struct vertex {
                int value;
                struct vertex *next;
                struct edge *list;
};
typedef struct vertex *Vertex;

struct edge {
                Vertex to; 
                struct edge *next;
};
typedef struct edge *Edge;

struct graph {
                int V; 
                int E;
                struct vertex *head;
};
typedef struct graph *Graph;

Graph GRAPHinit() {
	Graph G = malloc(sizeof *G);
	G->V=0;
	G->E=0;
	G->head=NULL;
	return G;
}

void GRAPHinsertV(Graph G, int value) {
	Vertex newV = malloc(sizeof newV);
	newV->value = value;
	newV->next = G->head;
	newV->list = NULL;
	G->head = newV;
	G->V++;
}

void GRAPHinsertEfromPointers(Graph G, Vertex V, Vertex W)
{
	Edge tmp = malloc(sizeof(struct edge));
	tmp->to = W;
	tmp->next = V->list;
	V->list = tmp;
}

Vertex findVertexFromValue(Graph G, int value)
{
	Vertex tmp;
	for(tmp = G->head;tmp!=NULL;tmp = tmp->next)
	{
		if(tmp->value==value)
			return tmp;
	}
	return NULL;
}

void GRAPHinsertEfromValues(Graph G, int valueV, int valueW)
{
	Vertex V, W;
	V = findVertexFromValue(G, valueV);
	W = findVertexFromValue(G, valueW);
	if(V!=NULL && W!=NULL)
	{
		GRAPHinsertEfromPointers(G, V, W);
	} else {
		fprintf(stderr, "\nValori non trovati\n");
	}
}

void GRAPHprint(Graph G)
{
	Vertex tmp;
	Edge list;
	for(tmp = G->head;tmp!=NULL;tmp=tmp->next)
	{
		fprintf(stdout,"V:%d\t",tmp->value);
		for(list = tmp->list;list!=NULL;list=list->next)
			fprintf(stdout,"%d\t",list->to->value);
		fprintf(stdout, "\n");
	}
}

int main()
{
	Graph G = GRAPHinit();
	GRAPHinsertV(G, 1);
	GRAPHinsertV(G, 3);
	GRAPHinsertV(G, 13);
	GRAPHinsertV(G, 6);
	GRAPHinsertV(G, 21);
	GRAPHinsertV(G, 41);
	GRAPHinsertEfromValues(G, 41,21);
	GRAPHinsertEfromValues(G, 41,13);
	GRAPHinsertEfromValues(G, 41,6);
	GRAPHinsertEfromValues(G, 1,21);
	GRAPHinsertEfromValues(G, 1,13);
	GRAPHprint(G);
	free(G);
}

syntax highlighted by Code2HTML, v. 0.9.1

main.c and data file for adjMatrix

17 Novembre 2008
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include "GRAPH.h"

void replace(char *in, char *what, char by_what)
{
	int what_len = strlen(what);
	for(;;)
	{
		char *str = strstr(in, what);
		if (!str)
			break;
		memcpy(str + 1, str + what_len, strlen(str + what_len) + 1);
		*str = by_what;
	}
}

void usage(void)
{
	fprintf(stdout, "-f filename   \tcreate graph from file filename\n");
	fprintf(stdout, "-s begin,end  \tsearch a path in the graph from begin to end\n");
	fprintf(stdout, "-o            \toriented graph\n");
	fprintf(stdout, "-w            \tweighted graph\n");
	fprintf(stdout, "-h            \tthis help\n");
}

int main(int argc, char *argv[])
{
	char *filename = NULL;
	char *tmp = NULL, *a, *b;
	int sw;
	int begin=-1;
	int end=-1;
	int oriented=0;
	int weighted=0;
	while((sw = getopt(argc, argv, "f:s:owh")) != -1)
	{
		switch(sw)
		{
			case 'f':
				filename = optarg;
				break;

		        case 's':
			        tmp = strtok(optarg, ", ");
				begin = atoi(tmp);
				tmp = strtok(NULL, ", ");
				end = atoi(tmp);
				break;

		        case 'o':
			        oriented=1;
				break;

		        case 'w':
			        weighted=1;
				break;

			case 'h':
			default:
				usage();
				return 1;
		}
	}

	Graph G;

	if(filename!=NULL)
	  {
	    fprintf(stdout, "Loading graph from file: %s\n", filename);
	    G = GRAPHloadfromfile(filename, weighted, oriented);
	  }

	if(begin!=-1)
	  {
	    fprintf(stdout, "Finding path between node %d and %d: \n", begin, end);
	    GRAPHpathsearch(G, begin, end);
	  }
	return 0;
}

30
1 2 1
0 3 5
5 7 8
12 29 10
11 13 1
23 22 3
21 18 76
21 19 3
19 17 4
17 6 3


syntax highlighted by Code2HTML, v. 0.9.1

adjMatrix.c

17 Novembre 2008
#include <stdio.h>
#include <stdlib.h>
#include "GRAPH.h"

#define MAX_LINE 20
/*#define DEBUG 1*/

struct graph {int V; int E; int **adj;};
Edge EDGE(int v, int w, int weight)
{
  Edge E;
  E.v = v;
  E.w = w;
  E.weight = weight;
  return E;
}

Graph GRAPHinit(int V)
{
  Graph G = malloc(sizeof *G) ;
  G->V = V; G->E = 0;
  G->adj = MATRIXint(V, V, 0);
  return G;
}

void GRAPHinsertE(Graph G, Edge e, int oriented)
{
  int v = e.v, w = e.w, weight = e.weight;
  if (G->adj[v][w] == 0) G->E++;
  G->adj[v][w] = weight;
  if(!oriented)
    G->adj[w][v] = weight;
}

void GRAPHremoveE(Graph G, Edge e, int oriented)
{
  int v = e.v, w = e.w, weight = e.weight;
  if (G->adj[v] [w] == 1) G->E--;
  G->adj[v][w] = 0;
  if(!oriented)
    G->adj[w][v] = 0;
}

int GRAPHedges(Edge a[], Graph G)
{
  int v, w, E = 0;
  for (v = 0; v < G->V; v++)
    for (w = v+1; w < G->V; w++)
      if (G->adj[v][w] >= 1)
        a[E++] = EDGE(v, w, G->adj[v][w]);
  return E;
}

int **MATRIXint(int r, int c, int val)
{
  int i, j;
  int **t = malloc(r * sizeof(int *));
  for (i = 0; i < r; i++)
    t[i] = malloc(c * sizeof(int));
  for (i = 0; i < r; i++)
    for (j = 0; j < c; j++)
      t[i][j] = val;
  return t;
}

void GRAPHprint(Graph G)
{
  int v, w, E = 0;
  for (v = 0; v < G->V; v++)
    {
      fprintf(stdout, "%d\n", v);
      for (w = v+1; w < G->V; w++)
      {
	if (G->adj[v][w] >= 1)
	  fprintf(stdout, "\t=>%d: %d\t", w, G->adj[v][w]);
      }
    }
}

Graph GRAPHloadfromfile(char *filename, int weighted, int oriented)
{
  FILE *fp;
  char line[MAX_LINE];
  Graph G;
  int nodes, v, w;
  //weight value for arc
  int wVal = 1;
  if((fp=fopen(filename, "r"))==NULL)
    {
      fprintf(stdout, "Unable to open %s\nEXITING!\n", filename);
      exit(0);
    }
  fgets(line, MAX_LINE, fp);
  sscanf(line, "%d", &nodes);
  G = GRAPHinit(nodes);

  while(!feof(fp))
    {
      fgets(line, MAX_LINE, fp);
      if(weighted)
	sscanf(line,"%d %d %d", &v, &w, &wVal);
      else
	sscanf(line, "%d %d", &v, &w);
      if(oriented)
	GRAPHinsertE(G, EDGE(v,w,wVal), 1);
      else
	GRAPHinsertE(G, EDGE(v,w,wVal), 0);
    }
  fclose(fp);
  return G;
}

/*
  search for a path
  value 0: starting node
  value -1: unvisited node
*/
int GRAPHpathsearch(Graph G, int begin, int end)
{
  int i, v, w;
  int nodes[G->V];
  for(i=0; i<G->V; i++)
    nodes[i] = -1;
  GRAPHpathrecursivelabel(G, nodes, begin, end, 0);

  #ifdef DEBUG
    fprintf(stdout, "Nodes: %d\n", G->V);
    for(i=0; i<G->V; i++)
      fprintf(stdout, "%d: %d\n", i, nodes[i]);
  #endif

  if(nodes[end]!=-1)
    fprintf(stdout, "PATH EXISTS!\n");
  else
    fprintf(stdout, "PATH DOES NOT EXISTS!\n");
}

int GRAPHpathrecursivelabel(Graph G, int *nodes, int from, int to, int value)
{
  int w, i;

  #ifdef DEBUG
    fprintf(stdout, "Nodes: %d\n", G->V);
    for(i=0; i<G->V; i++)
      fprintf(stdout, "%d: %d\n", i, nodes[i]);
  #endif

  if(nodes[from]>=0)
    return to;
  nodes[from]=value;
  if(from==to)
      return to;
  for(w=0; w<G->V; w++)
    {

      #ifdef DEBUG
	fprintf(stdout, "Trying: %d=>%d = %d\n", from, w, G->adj[from][w]);
	getchar();
      #endif

      if(G->adj[from][w]!=0 && nodes[to]<0)
	{
	  GRAPHpathrecursivelabel(G, nodes, w, to, value+1);
	}
    }
  return from;
}

syntax highlighted by Code2HTML, v. 0.9.1

GRAPH.h

17 Novembre 2008
typedef struct { int v; int w; int weight;} Edge;
Edge EDGE(int, int, int);
typedef struct graph *Graph;
Graph GRAPHinit(int);
void  GRAPHinsertE(Graph, Edge, int);
void  GRAPHremoveE(Graph, Edge, int);
int   GRAPHedges(Edge [], Graph G);
Graph GRAPHcopy(Graph);
void  GRAPHdestroy(Graph);
void  GRAPHprint(Graph G);
Graph GRAPHloadfromfile(char *filename, int weighted, int oriented);

int **MATRIXint(int, int, int);

//graph path
int GRAPHpathsearch(Graph G, int begin, int end);
int GRAPHpathrecursivelabel(Graph G, int *vert, int from, int to, int value);

syntax highlighted by Code2HTML, v. 0.9.1

keyStructInt.h

17 Novembre 2008
#ifndef __STDIOH__
#include <stdio.h>
#define __STDIOH__ 1
#endif

#ifndef __STDLIBH__
#include <stdlib.h>
#define __STDLIBH__ 1
#endif

typedef struct keyStruct {
  int intKey;
}keyStruct;
#define __KEYSTRUCT__ 1

keyStruct* createKeyStruct(int x);
void copyVal(keyStruct *from, keyStruct *to);
char* printVal(keyStruct *val);

syntax highlighted by Code2HTML, v. 0.9.1

keyStructInt.c

17 Novembre 2008
#include "keyStructInt.h"

keyStruct* createKeyStruct(int x)
{
  keyStruct *newKey = (keyStruct *)malloc(sizeof(keyStruct));
  newKey->intKey = x;
  return newKey;
}

void copyVal(keyStruct *from, keyStruct *to)
{
  to->intKey = from->intKey;
}
char* printVal(keyStruct *val)
{
  char* str = malloc(20*sizeof(char));
  sprintf(str, "%d", (int)val->intKey);
  return str;
}

syntax highlighted by Code2HTML, v. 0.9.1

keyStructString.h

17 Novembre 2008
#ifndef __STDIOH__
#include <stdio.h>
#define __STDIOH__ 1
#endif

#ifndef __STDLIBH__
#include <stdlib.h>
#define __STDLIBH__ 1
#endif

#ifndef _STRINGH__
#include <string.h>
#endif

typedef struct keyStruct {
  char *stringKey;
}keyStruct;

#define __KEYSTRUCT__ 1

keyStruct* createKeyStruct(char *x);
void copyVal(keyStruct *from, keyStruct *to);
char* printVal(keyStruct *val);

syntax highlighted by Code2HTML, v. 0.9.1

keyStructString.c

17 Novembre 2008
#include "keyStructString.h"

keyStruct* createKeyStruct(char *x)
{
  keyStruct *newKey = (keyStruct *)malloc(sizeof(keyStruct));
  newKey->stringKey = malloc(sizeof(x));
  strcpy(newKey->stringKey, x);
  return newKey;
}

void copyVal(keyStruct *from, keyStruct *to)
{
  to->stringKey = malloc(sizeof(from->stringKey));
  strcpy(to->stringKey, from->stringKey);
}

char* printVal(keyStruct *val)
{
  return val->stringKey;
}

syntax highlighted by Code2HTML, v. 0.9.1