Beispiellösung

Content

#include <stdio.h>
#include <stdlib.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <unistd.h>

#define N 1000 /* number of child processes */

/* return real time in seconds since some arbitrary point in the past */
double walltime() {
   static int ticks_per_second = 0;
   if (!ticks_per_second) {
      ticks_per_second = sysconf(_SC_CLK_TCK);
   }
   struct tms timebuf;
   /* times returns the number of real time ticks passed since some
      arbitrary point in the past */
   return (double) times(&timebuf) / ticks_per_second;
}

volatile char global[1048576];

int main() {
   int pagesize = getpagesize();
   for (size_t count = 0; count < sizeof(global) / pagesize; ++count) {
      double t0 = walltime();
      for (int i = 1; i <= N; ++i) {
	 pid_t child = fork();
	 if (child == -1) {
	    perror("unable to fork"); exit(1);
	 }
	 if (child == 0) {
	    /* child process */
	    for (size_t index = 0; index < count; ++index) {
	       global[index*pagesize] = i;
	    }
	    _exit(i);
	 }
      }

      /* parent process */
      pid_t child; int stat;
      while ((child = wait(&stat)) >= 0) {
	 /* nothing to be done */
      }
      double t1 = walltime() - t0;
      printf("%d %.4lf\n", (int) count, t1*1000*1000 / N);
   }
}
set terminal svg size 900, 500
set output "copy-on-write.svg"
set title "Real time of fork and wait in dependence of updated pages"
set xlabel "number of updated pages"
set ylabel "avg time in us"
set key outside
set pointsize 0.5
plot "copy-on-write.out" using 1:2 with linespoints lt 2 \
   title "Linux 4.9.0-8-amd64 on Intel i5-3470 3.20GHz"

Zu den Fragen

Übersetzung und Ausführung

heim$ gcc -Wall -o timed-forkandwait-with-update timed-forkandwait-with-update.c
heim$ ./timed-forkandwait-with-update >copy-on-write.out
heim$ gnuplot copy-on-write.gnuplot
heim$ 

Die seltsame Treppenstruktur ergibt sich durch die grobe Granularität der Ticks:

#include <stdio.h>
#include <unistd.h>

int main() {
   printf("%ld\n", sysconf(_SC_CLK_TCK));
}
heim$ gcc -o tickspersec tickspersec.c
heim$ ./tickspersec
100
heim$ 

100 Ticks pro Sekunde entspricht einer Auflösung von 10 ms. Durch die 1000 Prozesse kommen wir zu einer Auflösung von 10 us.