maggiore del secondo.}
\end{functions}
-
La funzione \func{alphasort} deriva da BSD ed è presente in Linux fin dalle
libc4\footnote{la versione delle libc4 e libc5 usa però come argomenti dei
puntatori a delle strutture \struct{dirent}; le glibc usano il prototipo
del numero di versione (cioè qualcosa per cui \file{file10} viene comunque
dopo \func{file4}.)
+Un semplice esempio dell'uso di queste funzioni è riportato in
+\figref{fig:file_my_ls}, dove si è riportata la sezione principale di un
+programma che, usando la routine di scansione illustrata in
+\figref{fig:file_dirscan}, stampa i nomi dei file contenuti in una directory e
+la relativa dimensione (in sostanza una versione semplificata del comando
+\cmd{ls}).
+
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h> /* directory */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h>
+
+/* computation function for DirScan */
+int do_ls(struct dirent * direntry);
+/* main body */
+int main(int argc, char *argv[])
+{
+ ...
+ if ((argc - optind) != 1) { /* There must be remaing parameters */
+ printf("Wrong number of arguments %d\n", argc - optind);
+ usage();
+ }
+ DirScan(argv[1], do_ls);
+ exit(0);
+}
+/*
+ * Routine to print file name and size inside DirScan
+ */
+int do_ls(struct dirent * direntry)
+{
+ struct stat data;
+
+ stat(direntry->d_name, &data); /* get stat data */
+ printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
+ return 0;
+}
+ \end{lstlisting}
+ \caption{Esempio di codice per eseguire la lista dei file contenuti in una
+ directory.}
+ \label{fig:file_my_ls}
+\end{figure}
+
+Il programma è estremamente semplice; in \figref{fig:file_my_ls} si è omessa
+la parte di gestione delle opzioni (che prevede solo l'uso di una funzione per
+la stampa della sintassi, anch'essa omessa) ma il codice completo potrà essere
+trovato coi sorgenti allegati nel file \file{myls.c}.
+
+In sostanza tutto quello che fa il programma, dopo aver controllato
+(\texttt{\small 10--13}) di avere almeno un parametro (che indicherà la
+directory da esaminare) è chiamare (\texttt{\small 14}) la funzione
+\func{DirScan} per eseguire la scansione, usando la funzione \code{do\_ls}
+(\texttt{\small 20--26}) per fare tutto il lavoro.
+
+Quest'ultima si limita (\texttt{\small 23}) a chiamare \func{stat} sul file
+indicato dalla directory entry passata come argomento (il cui nome è appunto
+\var{direntry->d\_name}), memorizzando in una opportuna struttura \var{data} i
+dati ad esso relativi, per poi provvedere (\texttt{\small 24}) a stampare il
+nome del file e la dimensione riportata in \var{data}.
+
+Dato che la funzione verrà chiamata all'interno di \func{DirScan} per ogni
+voce presente questo è sufficiente a stampare la lista completa dei file e
+delle relative dimensioni. Si noti infine come si restituisca sempre 0 come
+valore di ritorno per indicare una esecuzione senza errori.
+
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h> /* directory */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h>
+
+/*
+ * Function DirScan:
+ *
+ * Input: the directory name and a computation function
+ * Return: 0 if OK, -1 on errors
+ */
+int DirScan(char * dirname, int(*compute)(struct dirent *))
+{
+ DIR * dir;
+ struct dirent *direntry;
+
+ if ( (dir = opendir(dirname)) == NULL) { /* oper directory */
+ printf("Opening %s\n", dirname); /* on error print messages */
+ perror("Cannot open directory"); /* and then return */
+ return -1;
+ }
+ fd = dirfd(dir); /* get file descriptor */
+ fchdir(fd); /* change directory */
+ /* loop on directory entries */
+ while ( (direntry = readdir(dir)) != NULL) { /* read entry */
+ if (compute(direntry)) { /* execute function on it */
+ return -1; /* on error return */
+ }
+ }
+ closedir(dir);
+ return 0;
+}
+
+ \end{lstlisting}
+ \caption{Codice della routine di scansione di una directory contenuta nel
+ file \file{DirScan.c}.}
+ \label{fig:file_dirscan}
+\end{figure}
+Tutto il grosso del lavoro è svolto dalla funzione \func{DirScan}, riportata
+in \figref{fig:file_dirscan}. La funzione è volutamente generica e permette di
+eseguire una funzione, passata come secondo argomento, su tutte le voci di una
+directory. La funzione inizia con l'aprire (\texttt{\small 19--23}) uno
+stream sulla directory passata come primo argomento, stampando un messaggio in
+caso di errore.
+
+Il passo successivo (\texttt{\small 24--25}) è cambiare directory di lavoro
+(vedi \secref{sec:file_work_dir}), usando in sequenza le funzione \func{dirfd}
+e \func{fchdir} (in realtà si sarebbe potuto usare direttamente \func{chdir}
+su \var{dirname}), in modo che durante il successivo ciclo (\texttt{\small
+ 27--31}) sulle singole voci dello stream ci si trovi all'interno della
+directory.\footnote{questo è essenziale al funzionamento della funzione
+ \code{do\_ls} (e ad ogni funzione che debba usare il campo \var{d\_name}, in
+ quanto i nomi dei file memorizzati all'interno di una struttura
+ \struct{dirent} sono sempre relativi alla directory in questione, e senza
+ questo posizionamento non si sarebbe potuto usare \func{stat} per ottenere
+ le dimensioni.}
+
+Avendo usato lo stratagemma di fare eseguire tutte le manipolazioni necessarie
+alla funzione passata come secondo argomento, il ciclo di scansione della
+directory è molto semplice; si legge una voce alla volta (\texttt{\small 27})
+all'interno di una istruzione di \code{while} e fintanto che si riceve una
+voce valida (cioè un puntatore diverso da \val{NULL}) si esegue
+(\texttt{\small 27}) la funzione di elaborazione \var{compare} (che nel nostro
+caso sarà \code{do\_ls}), ritornando con un codice di errore (\texttt{\small
+ 28}) qualora questa presenti una anomalia (identificata da un codice di
+ritorno negativo).
+
+Una volta terminato il ciclo la funzione si conclude con la chiusura
+(\texttt{\small 32}) dello stream\footnote{nel nostro caso, uscendo subito
+ dopo la chiamata, questo non servirebbe, in generale però l'operazione è
+ necessaria, dato che la funzione può essere invocata molte volte all'interno
+ dello stesso processo, per cui non chiudere gli stream comporterebbe un
+ consumo progressivo di risorse, con conseguente rischio di esaurimento delle
+ stesse} e la restituzione (\texttt{\small 33}) del codice di operazioni
+concluse con successo.
\subsection{La directory di lavoro}
struttura \var{lock} per il rilascio del lock, che viene effettuato
(\texttt{\small 39--42}) subito dopo.
- \subsection{Il \textit{memory mapping} anonimo}
+
+\subsection{Il \textit{memory mapping} anonimo}
\label{sec:ipc_mmap_anonymous}
Abbiamo già visto che quando i processi sono \textsl{correlati}\footnote{se
--- /dev/null
+/* DirMonitor.c
+ *
+ * Copyright (C) 2002 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*****************************************************************************
+ *
+ * File DirMonitor:
+ *
+ * An example for shared memory use: monitor a directory status,
+ * saving data in a shared memory segment
+ *
+ * Author: S. Piccardi Jan. 2003
+ *
+ * $Id: DirMonitor.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h> /* directory */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h>
+
+#include "Gapil.h"
+
+/* Help printing routine */
+void usage(void);
+/* computation function for DirScan */
+int ComputeValues(struct dirent * direntry);
+
+/* global variable for shared memory segment */
+int shmid; /* Shared memory identifier */
+
+int main(int argc, char *argv[])
+{
+ int i;
+ int mutex;
+ /*
+ * Input section: decode command line parameters
+ * Use getopt function
+ */
+ opterr = 0; /* don't want writing to stderr */
+ while ( (i = getopt(argc, argv, "hs:l:wrbf")) != -1) {
+ switch (i) {
+ /*
+ * Handling options
+ */
+ case 'h': /* help option */
+ printf("Wrong -h option use\n");
+ usage();
+ return -1;
+ break;
+ case '?': /* unrecognized options */
+ printf("Unrecognized options -%c\n",optopt);
+ usage();
+ default: /* should not reached */
+ usage();
+ }
+ }
+ /* ***********************************************************
+ *
+ * Options processing completed
+ *
+ * Main code beginning
+ *
+ * ***********************************************************/
+ if ((argc - optind) != 1) { /* There must be remaing parameters */
+ printf("Wrong number of arguments %d\n", argc - optind);
+ usage();
+ }
+
+ DirScan(argv[1], ComputeValues);
+ exit(0);
+}
+/*
+ * Routine to print file name and size inside DirScan
+ */
+int do_ls(struct dirent * direntry)
+{
+ struct stat data;
+ stat(direntry->d_name, &data); /* get stat data */
+ printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
+ return 0;
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+ printf("Program myls: list file in a directory \n");
+ printf("Usage:\n");
+ printf(" myls [-h] dirname \n");
+ printf(" -h print this help\n");
+ exit(1);
+}
--- /dev/null
+/* DirScan.c
+ *
+ * Copyright (C) 2002 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*****************************************************************************
+ *
+ * File DirScan.c: routine for directory scan
+ *
+ * Author: S. Piccardi Jan. 2003
+ *
+ * $Id: DirScan.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h> /* directory */
+#include <stdlib.h> /* C standard library */
+
+/*
+ * Function DirScan:
+ *
+ * Scan all entries in a directory, executing the provided function
+ * on each one.
+ *
+ * Input: the directory name and a computation function
+ * Return: 0 if OK, -1 on errors
+ */
+int DirScan(char * dirname, int(*compute)(struct dirent *))
+{
+ DIR * dir;
+ struct dirent *direntry;
+ int fd;
+
+ if ( (dir = opendir(dirname)) == NULL) { /* oper directory */
+ printf("Opening %s\n", dirname); /* on error print messages */
+ perror("Cannot open directory"); /* and then return */
+ return -1;
+ }
+ fd = dirfd(dir); /* get file descriptor */
+ fchdir(fd); /* change directory */
+ /* loop on directory entries */
+ while ( (direntry = readdir(dir)) != NULL) { /* read entry */
+ if (compute(direntry)) { /* execute function on it */
+ return -1; /* on error return */
+ }
+ }
+ closedir(dir);
+ return 0;
+}
OBJ = SockRead.o SockWrite.o SigHand.o Mutex.o SharedMem.o LockFile.o
FINAL = forktest errcode echo echod daytimed iterdaytimed daytime testfopen \
- testren fortune fortuned mqfortune mqfortuned flock
+ testren fortune fortuned mqfortune mqfortuned flock myls
$(LIB): $(OBJ)
gcc -shared $^ -o $@
all: $(FINAL) $(LIB)
+myls: myls.c DirScan.c
+ $(CC) $^ -o $@
flock: Flock.c
$(CC) $(CFLAGJ) $^ -o $@
--- /dev/null
+/* myls.c
+ *
+ * Copyright (C) 2002 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*****************************************************************************
+ *
+ * File myls.c: An example ls
+ *
+ * Author: S. Piccardi Jan. 2003
+ *
+ * $Id: myls.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h> /* directory */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h>
+
+/*
+ * Program myls
+ *
+ * List files and their size inside a given directory
+ */
+/* Help printing routine */
+void usage(void);
+/* computation function for DirScan */
+int do_ls(struct dirent * direntry);
+
+int main(int argc, char *argv[])
+{
+ int i;
+ /*
+ * Input section: decode command line parameters
+ * Use getopt function
+ */
+ opterr = 0; /* don't want writing to stderr */
+ while ( (i = getopt(argc, argv, "hs:l:wrbf")) != -1) {
+ switch (i) {
+ /*
+ * Handling options
+ */
+ case 'h': /* help option */
+ printf("Wrong -h option use\n");
+ usage();
+ return -1;
+ break;
+ case '?': /* unrecognized options */
+ printf("Unrecognized options -%c\n",optopt);
+ usage();
+ default: /* should not reached */
+ usage();
+ }
+ }
+ /* ***********************************************************
+ *
+ * Options processing completed
+ *
+ * Main code beginning
+ *
+ * ***********************************************************/
+ if ((argc - optind) != 1) { /* There must be remaing parameters */
+ printf("Wrong number of arguments %d\n", argc - optind);
+ usage();
+ }
+ DirScan(argv[1], do_ls);
+ exit(0);
+}
+/*
+ * Routine to print file name and size inside DirScan
+ */
+int do_ls(struct dirent * direntry)
+{
+ struct stat data;
+ stat(direntry->d_name, &data); /* get stat data */
+ printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
+ return 0;
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+ printf("Program myls: list file in a directory \n");
+ printf("Usage:\n");
+ printf(" myls [-h] dirname \n");
+ printf(" -h print this help\n");
+ exit(1);
+}