<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://so.v2.cs.unibo.it/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aletri</id>
	<title>Sistemi Operativi - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://so.v2.cs.unibo.it/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aletri"/>
	<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php/Special:Contributions/Aletri"/>
	<updated>2026-05-11T11:05:43Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.5</generator>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1348</id>
		<title>Esercizi con System Call</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1348"/>
		<updated>2016-04-26T14:32:20Z</updated>

		<summary type="html">&lt;p&gt;Aletri: /* Client */ add more sleep to timer to get long messages&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi contengono esempi di uso delle System-Call.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:03, 2 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
Il gatto di Schr&amp;amp;ouml;dinger: Fork e' vero o falso?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
  if (fork())&lt;br /&gt;
    printf(&amp;quot;fork is true\n&amp;quot;);&lt;br /&gt;
  else&lt;br /&gt;
    printf(&amp;quot;fork is false\n&amp;quot;);&lt;br /&gt;
  usleep(100000);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
il programma stampa entrambi i risultati perché la system call fork() crea un processo figlio identico al padre, questa system call ha come valore di ritorno al thread padre il pid del processo figlio (che essendo diverso da 0 è true) e al thread figlio ritorna 0, quindi il processo padre riceve un valore diverso da 0 (pid del figlio) e stampa true, mentre il processo figlio riceve 0, non entra nel if e stampa, ovviamente false.&lt;br /&gt;
&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
Open() Write() Read()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
/*IL PROGRAMMA APRE UN FILE SUL QUALE FA DELLE OPERAZIONI DI LETTURA E SCRITTURA*/&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_CHAR 100000&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	&lt;br /&gt;
	int fd, c, n_read;&lt;br /&gt;
	int fine = EOF;&lt;br /&gt;
        int index = 0;&lt;br /&gt;
	char arr[MAX_CHAR];&lt;br /&gt;
	char c_arr_read[MAX_CHAR];&lt;br /&gt;
	const char *path = //inserisci qui il percorso del file che vuoi aprire, se il file specificato non esiste, la open fallisce e il &lt;br /&gt;
                           //programma termina con un codice di errore&lt;br /&gt;
	fd = open(path, O_RDWR);&lt;br /&gt;
&lt;br /&gt;
	if(fd == -1){&lt;br /&gt;
		printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
		printf(&amp;quot;Open failed, Err: %d\n&amp;quot;, errno);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	if( (n_read = read(fd, &amp;amp;c_arr_read, MAX_CHAR)) &amp;gt; 0 ) {&lt;br /&gt;
		printf(&amp;quot;file non vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
		write(fd, &amp;amp;fine, 0);&lt;br /&gt;
	} else printf(&amp;quot;file vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
&lt;br /&gt;
	//printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
	printf(&amp;quot;Open().\n&amp;quot;);&lt;br /&gt;
	while((c = getchar()) != EOF &amp;amp;&amp;amp; index &amp;lt; MAX_CHAR){&lt;br /&gt;
		arr[index] = c;&lt;br /&gt;
		index++;&lt;br /&gt;
	}&lt;br /&gt;
	//printf(&amp;quot;sizeof arr: %d\n&amp;quot;, sizeof(arr));&lt;br /&gt;
	write(fd, &amp;amp;arr, index);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
segnali + fork&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pty.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utmp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
&lt;br /&gt;
sigset_t usr12mask;&lt;br /&gt;
sigset_t usr1mask;&lt;br /&gt;
int status;&lt;br /&gt;
int fd, fdout;&lt;br /&gt;
char name[80];&lt;br /&gt;
static int bit;&lt;br /&gt;
char *ar[2] = {&amp;quot;bash&amp;quot;, NULL};&lt;br /&gt;
&lt;br /&gt;
void usr12action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	if (num == SIGCHLD)&lt;br /&gt;
		bit=-1;&lt;br /&gt;
	else {&lt;br /&gt;
		bit = (num == SIGUSR2);&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void usr1action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char_to_bin(unsigned char x, void *rec){&lt;br /&gt;
	int i;&lt;br /&gt;
	pid_t *r = rec;&lt;br /&gt;
&lt;br /&gt;
	for(i=7; i&amp;gt;=0; i--){&lt;br /&gt;
		char f = x &amp;gt;&amp;gt; i &amp;amp; 1;&lt;br /&gt;
		kill(*r,f?SIGUSR2:SIGUSR1);&lt;br /&gt;
		sigsuspend(&amp;amp;usr1mask);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void *v)&lt;br /&gt;
{&lt;br /&gt;
	sigsuspend(&amp;amp;usr12mask);&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bin2char(int (*f)(void *opaque), void *opaque) {&lt;br /&gt;
	int i;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (i=c=0; i&amp;lt;8; i++) {&lt;br /&gt;
		int n=f(opaque);&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return -1;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			static struct sigaction sa={&lt;br /&gt;
				.sa_sigaction=usr12action,&lt;br /&gt;
				.sa_flags=SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;,getpid());&lt;br /&gt;
&lt;br /&gt;
			sigfillset(&amp;amp;usr12mask);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGINT);&lt;br /&gt;
			sigprocmask(SIG_SETMASK,&amp;amp;usr12mask,NULL);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR2);&lt;br /&gt;
			sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGUSR2,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGCHLD,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c=bin2char(readbit,stdin)) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
			if (waitpid(pid, &amp;amp;status, 0) != pid)  status = -1;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			char *path;&lt;br /&gt;
			char *sppid;&lt;br /&gt;
			pid_t ppid=getppid();&lt;br /&gt;
			asprintf(&amp;amp;path,&amp;quot;/proc/%d/exe&amp;quot;,ppid);&lt;br /&gt;
			asprintf(&amp;amp;sppid,&amp;quot;%d&amp;quot;,ppid);&lt;br /&gt;
			execl(&amp;quot;/usr/bin/xterm&amp;quot;, &amp;quot;xterm&amp;quot;, &amp;quot;-e&amp;quot;, path, sppid, (void *) 0);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		unsigned char buf[BUFSIZE];&lt;br /&gt;
		unsigned char *s;&lt;br /&gt;
		pid_t receiver=atoi(argv[1]);&lt;br /&gt;
&lt;br /&gt;
		static struct sigaction sa={.sa_sigaction=usr1action};&lt;br /&gt;
		sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		sigfillset(&amp;amp;usr1mask);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGINT);&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;usr1mask,NULL);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGUSR1);&lt;br /&gt;
		if (argc == 2){&lt;br /&gt;
			while ((s=fgets(buf,BUFSIZE,stdin))!=NULL){&lt;br /&gt;
				while (*s){&lt;br /&gt;
					char_to_bin(*s++, &amp;amp;receiver);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
il programma in questione &amp;quot;unisce&amp;quot; di fatto i due programmi sigsend e sigrec.&lt;br /&gt;
l'idea è quella che venga lanciato un unico processo e aprire un nuovo terminale dove contiunare l'esecuzione del figlio creato attraverso la fork.&lt;br /&gt;
Possiamo quindi sfruttare il fatto che i due processi (essendo padre e figlio) conoscono i rispettivi pid e quindi automatizzare questa parte senza fornire alcun pid in input.&lt;br /&gt;
è possibile anche fornire un pid come argomento per comunicare con processi diversi.&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 (Fork del programma 2 di ([[User:Simone|Simone]]) )==&lt;br /&gt;
Sono state effettuate delle piccole modifiche rispetto al programma 2 e inoltre sono stati aggiunti dei commenti per rendere più intuitivo e leggibile il codice.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
sigset_t receiverMask;&lt;br /&gt;
sigset_t senderMask;&lt;br /&gt;
static int bit;&lt;br /&gt;
&lt;br /&gt;
void receiverAction(int num, siginfo_t *info, void *useless) { &lt;br /&gt;
	if (num == SIGCHLD)	// Se il processo figlio del ricevente è terminato&lt;br /&gt;
		bit = EOF;&lt;br /&gt;
	else{&lt;br /&gt;
		bit = (num == SIGUSR2);		// Codifico 1 con il segnale SIGUSR2 e 0 con SIGUSR1&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);	// Invio il segnale SIGUSR1 al mittente&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void senderAction(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void write_bin(unsigned char x, pid_t *recv){	/* Funzione che riguarda il mittente */&lt;br /&gt;
	unsigned int i;&lt;br /&gt;
	for(i=0x80; i&amp;gt;0; i&amp;gt;&amp;gt;=1){	// Parto da 10000000, man mano shifto a destra, 01000000, 00100000 ecc ecc, fino a 00000000&lt;br /&gt;
		kill(*recv, (x &amp;amp; i) ? SIGUSR2 : SIGUSR1);	// Invio segnale al ricevente&lt;br /&gt;
		sigsuspend(&amp;amp;senderMask);			// Attendo segnale di ritorno&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void){&lt;br /&gt;
	sigsuspend(&amp;amp;receiverMask);     // Sospende il processo e attende un segnale&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int read_char(){	/* Funzione che riguarda il ricevente */&lt;br /&gt;
	int i, c;&lt;br /&gt;
	for (i = c = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
		int n = readbit();&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return EOF;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){	/* PROCESSO PADRE (PROCESSO RICEVENTE) */&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Il valore di sa_flag permette di specificare vari aspetti del comportamento di sigaction:&lt;br /&gt;
			 * SA_SIGINFO specifica che si vuole usare un gestore in forma estesa usando sa_sigaction al&lt;br /&gt;
			 * posto di sa_handler. Il valore di sa_sigaction specifica la funzione da chiamare, permettendo&lt;br /&gt;
			 * di usare un gestore piu complesso, in grado di ricevere informazioni piu dettagliate dal&lt;br /&gt;
			 * sistema, attraverso la struttura siginfo_t&lt;br /&gt;
			 */&lt;br /&gt;
			struct sigaction sa = {&lt;br /&gt;
				.sa_sigaction = receiverAction,&lt;br /&gt;
				.sa_flags = SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;, getpid());&lt;br /&gt;
&lt;br /&gt;
			/* Inserisci tutti i segnali nell'insieme receiverMask */&lt;br /&gt;
			sigfillset(&amp;amp;receiverMask);&lt;br /&gt;
&lt;br /&gt;
			/* Elimina il segnale SIGINT dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGINT);&lt;br /&gt;
&lt;br /&gt;
			/* Setta la maschera dei segnali del processo con l'insieme receiverMask.&lt;br /&gt;
			 * Il valore NULL indica che la maschera attuale del processo non verrà salvata. */&lt;br /&gt;
			sigprocmask(SIG_SETMASK, &amp;amp;receiverMask, NULL);&lt;br /&gt;
			&lt;br /&gt;
			/* Elimina il segnale SIGCHLD, SIGUSR1 e SIGUSR2 dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR2);&lt;br /&gt;
			&lt;br /&gt;
			/* Setta l'azione sa per i segnali SIGUSR1, SIGUSR2 e SIGCHLD. &lt;br /&gt;
			 * Il valore NULL indica che l’azione corrente non viene restituita indietro. */&lt;br /&gt;
			sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGUSR2, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGCHLD, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c = read_char()) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
		&lt;br /&gt;
		}&lt;br /&gt;
		else if(pid == 0){	// PROCESSO FIGLIO&lt;br /&gt;
			char *cmd;&lt;br /&gt;
			pid_t ppid = getppid();	/* PID del processo padre (ricevente) */&lt;br /&gt;
&lt;br /&gt;
                        /* Avvio un altro terminale eseguendo lo stesso programma con parametri di input */&lt;br /&gt;
			asprintf(&amp;amp;cmd, &amp;quot;xterm -e /proc/%d/exe %d&amp;quot;, ppid, ppid);	&lt;br /&gt;
			system(cmd);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
		else{	// Errore Fork&lt;br /&gt;
			fprintf(stderr, &amp;quot;Errore fork&amp;quot;);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {	/* PROCESSO MITTENTE */&lt;br /&gt;
		unsigned char buf[BUFSIZE], *read;&lt;br /&gt;
		pid_t receiver = atoi(argv[1]);	   // Pid del ricevente&lt;br /&gt;
		&lt;br /&gt;
		/* Setto una banale azione (usr1action) alla ricezione del segnale SIGUSR1*/&lt;br /&gt;
		struct sigaction sa = {.sa_sigaction = senderAction}; &lt;br /&gt;
		sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		&lt;br /&gt;
		sigfillset(&amp;amp;senderMask);		        // Inserisco tutti i segnali nell'insieme senderMask&lt;br /&gt;
		sigdelset(&amp;amp;senderMask, SIGINT); 		// e cancello dall'insieme il segnale SIGINT.&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;senderMask,NULL);	// Setto la maschera creata per il processo corrente, senza salvare la precedente.&lt;br /&gt;
		sigdelset(&amp;amp;senderMask,SIGUSR1);			// Elimino il segnale SIGUSR1 dall'insieme.&lt;br /&gt;
		if (argc == 2){					// Se i paramentri in input sono 2&lt;br /&gt;
			while ((read = fgets(buf,BUFSIZE,stdin)) != NULL){     // Leggo dallo stdin&lt;br /&gt;
				while (*read)				       // Leggo tutta la stringa&lt;br /&gt;
					write_bin(*read++, &amp;amp;receiver);	       // Invio ogni singolo carattere della stringa al ricevente&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= programma 5 =&lt;br /&gt;
==Secret channel with inotify==&lt;br /&gt;
Stavo leggendo sul libro che e' possibile creare un canale di comunicazione segreto praticamente con ogni cosa all'interno di un sistema UNIX. In particolare mi ha interessato il caso di creare un canale mono direzionale tramite l'apertura dei file in lettura o scrittura e ho voluto provare a implementarne uno. Questi canali sono quasi impossibili da scovare per un amministratore di sistema e potrebbero permettere lo scambio di informazioni illecite. &lt;br /&gt;
Una cosa interessante e' che a quanto pare il kernel ha bisogno di qualche millisecondo per eseguire la inotify e che una precedente implementazione senza delay portava all'arrivo di messaggi sbagliati.&lt;br /&gt;
&lt;br /&gt;
===Server===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void printChar(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        char c;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1)&lt;br /&gt;
                        buffer[i]= '1';&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        c = strtol(buffer, 0, 2);&lt;br /&gt;
        printf(&amp;quot;%c&amp;quot;, c);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void handle_events (int fd, int wd, char *bin_message,int *current_bit){&lt;br /&gt;
        char buf [4096]&lt;br /&gt;
        __attribute__ ((aligned(__alignof__(struct inotify_event))));&lt;br /&gt;
        const struct inotify_event *event;&lt;br /&gt;
        int i;&lt;br /&gt;
        ssize_t len;&lt;br /&gt;
        char *ptr;&lt;br /&gt;
&lt;br /&gt;
        //loop while inotify events can be read from the fd&lt;br /&gt;
        for (;;){&lt;br /&gt;
                len = read (fd, buf, sizeof (buf));&lt;br /&gt;
                if (len == -1 &amp;amp;&amp;amp; errno != EAGAIN){&lt;br /&gt;
                        perror (&amp;quot;read&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                //if the read returns with the errono EAGAIN exit from the loop&lt;br /&gt;
                if (len &amp;lt;= 0)&lt;br /&gt;
                        break;&lt;br /&gt;
                //loop between all events in the buffer&lt;br /&gt;
                for (ptr = buf; ptr &amp;lt; buf + len;&lt;br /&gt;
                                ptr += sizeof(struct inotify_event) + event-&amp;gt;len){&lt;br /&gt;
                        event = (const struct inotify_event *) ptr;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_NOWRITE){&lt;br /&gt;
                                //received 1&lt;br /&gt;
&lt;br /&gt;
                                *bin_message |= 0x01;&lt;br /&gt;
                        }&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_WRITE){&lt;br /&gt;
&lt;br /&gt;
                                //received 0&lt;br /&gt;
                                //do nothing to leave 0&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        &lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void main () {&lt;br /&gt;
        char buf;&lt;br /&gt;
        int fd;&lt;br /&gt;
        int wd;&lt;br /&gt;
        struct pollfd fds [2];&lt;br /&gt;
        int nfds;&lt;br /&gt;
        int poll_num;&lt;br /&gt;
        unsigned char message_str [4096] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int count = 0;&lt;br /&gt;
        int bit_wrote = 0;&lt;br /&gt;
         &lt;br /&gt;
        char path [100] = &amp;quot;/inofify/watched&amp;quot;;&lt;br /&gt;
        int t;&lt;br /&gt;
&lt;br /&gt;
        //create the file descriptor where inotify events has to be read&lt;br /&gt;
        fd = inotify_init1(IN_NONBLOCK);&lt;br /&gt;
        if (fd == -1) {&lt;br /&gt;
                perror(&amp;quot;inotify_init1&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        wd = inotify_add_watch (fd, path, IN_CLOSE_NOWRITE | IN_CLOSE_WRITE);&lt;br /&gt;
&lt;br /&gt;
        if (wd == -1 ){&lt;br /&gt;
                fprintf (stderr, &amp;quot;Cannot watch '%s' \n&amp;quot;, path);&lt;br /&gt;
                perror (&amp;quot;inotify_add_watch&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //prepare for the polling on the fd&lt;br /&gt;
&lt;br /&gt;
        nfds = 2;&lt;br /&gt;
        fds[0].fd = STDIN_FILENO;&lt;br /&gt;
        fds[0].events = POLLIN;&lt;br /&gt;
        fds[1].fd = fd;&lt;br /&gt;
        fds[1].events = POLLIN;&lt;br /&gt;
&lt;br /&gt;
        printf (&amp;quot;Listening for events... Press ENTER to terminate and show the message\n&amp;quot;);&lt;br /&gt;
        while (1){&lt;br /&gt;
&lt;br /&gt;
                poll_num = poll(fds,nfds, -1);&lt;br /&gt;
                if (poll_num == -1){&lt;br /&gt;
                        if (errno == EINTR)&lt;br /&gt;
                                continue;&lt;br /&gt;
                        perror (&amp;quot;poll&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                if (poll_num &amp;gt; 0){&lt;br /&gt;
                        if (fds[0].revents &amp;amp; POLLIN){&lt;br /&gt;
&lt;br /&gt;
                                //exit on ENTER key pressed emptying the stdin&lt;br /&gt;
                                while (read (STDIN_FILENO,&amp;amp;buf,1) &amp;gt; 0 &amp;amp;&amp;amp; buf != '\n') continue;&lt;br /&gt;
                                break;&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                        }&lt;br /&gt;
                        //notify an event occurred&lt;br /&gt;
                        if (fds[1].revents &amp;amp; POLLIN ){&lt;br /&gt;
                                if (bit_wrote &amp;lt; 8){&lt;br /&gt;
                                        printf(&amp;quot;..&amp;quot;);&lt;br /&gt;
                                        fflush(stdout);&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                        if (bit_wrote &amp;lt; 7){&lt;br /&gt;
                                                message_str[count] = message_str[count] &amp;lt;&amp;lt; 0x01;&lt;br /&gt;
                                        }&lt;br /&gt;
&lt;br /&gt;
                                }&lt;br /&gt;
                                else {&lt;br /&gt;
                                        bit_wrote = 0;&lt;br /&gt;
                                        count += 1;&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                }&lt;br /&gt;
                                bit_wrote += 1;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**********MESSAGE***********\n&amp;quot;);&lt;br /&gt;
        t = 0;&lt;br /&gt;
        while (t &amp;lt;= count ){&lt;br /&gt;
&lt;br /&gt;
                printChar(message_str[t]);&lt;br /&gt;
                t += 1;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**************************\n&amp;quot;);&lt;br /&gt;
        printf(&amp;quot;\nClosing...\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        exit(EXIT_SUCCESS);&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Client=== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void chat(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        int fd;&lt;br /&gt;
        char path [] = &amp;quot;watched&amp;quot;;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        const struct timespec timer = {&lt;br /&gt;
                .tv_sec = 0,&lt;br /&gt;
                .tv_nsec = 5000000&lt;br /&gt;
        };&lt;br /&gt;
        struct timespec s;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1){&lt;br /&gt;
&lt;br /&gt;
                        buffer[i] = '1';&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        for (a = 0; a &amp;lt; 8; a++) {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                if (buffer[a] == '0'){&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_WRONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                else{&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_RDONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                nanosleep(&amp;amp;timer,&amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
void main (){&lt;br /&gt;
        char message[1024] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int bit_message;&lt;br /&gt;
        int len = 0;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Type in \n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        fgets(message,100,stdin);&lt;br /&gt;
        printf(&amp;quot;You typed: %s&amp;quot;, message);&lt;br /&gt;
&lt;br /&gt;
        len = (unsigned)strlen(message);&lt;br /&gt;
        while (i &amp;lt; len -1){&lt;br /&gt;
                chat(message[i]);&lt;br /&gt;
                i++;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alessio Trivisonno&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1347</id>
		<title>Esercizi con System Call</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1347"/>
		<updated>2016-04-26T14:27:27Z</updated>

		<summary type="html">&lt;p&gt;Aletri: /* Server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi contengono esempi di uso delle System-Call.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:03, 2 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
Il gatto di Schr&amp;amp;ouml;dinger: Fork e' vero o falso?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
  if (fork())&lt;br /&gt;
    printf(&amp;quot;fork is true\n&amp;quot;);&lt;br /&gt;
  else&lt;br /&gt;
    printf(&amp;quot;fork is false\n&amp;quot;);&lt;br /&gt;
  usleep(100000);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
il programma stampa entrambi i risultati perché la system call fork() crea un processo figlio identico al padre, questa system call ha come valore di ritorno al thread padre il pid del processo figlio (che essendo diverso da 0 è true) e al thread figlio ritorna 0, quindi il processo padre riceve un valore diverso da 0 (pid del figlio) e stampa true, mentre il processo figlio riceve 0, non entra nel if e stampa, ovviamente false.&lt;br /&gt;
&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
Open() Write() Read()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
/*IL PROGRAMMA APRE UN FILE SUL QUALE FA DELLE OPERAZIONI DI LETTURA E SCRITTURA*/&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_CHAR 100000&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	&lt;br /&gt;
	int fd, c, n_read;&lt;br /&gt;
	int fine = EOF;&lt;br /&gt;
        int index = 0;&lt;br /&gt;
	char arr[MAX_CHAR];&lt;br /&gt;
	char c_arr_read[MAX_CHAR];&lt;br /&gt;
	const char *path = //inserisci qui il percorso del file che vuoi aprire, se il file specificato non esiste, la open fallisce e il &lt;br /&gt;
                           //programma termina con un codice di errore&lt;br /&gt;
	fd = open(path, O_RDWR);&lt;br /&gt;
&lt;br /&gt;
	if(fd == -1){&lt;br /&gt;
		printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
		printf(&amp;quot;Open failed, Err: %d\n&amp;quot;, errno);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	if( (n_read = read(fd, &amp;amp;c_arr_read, MAX_CHAR)) &amp;gt; 0 ) {&lt;br /&gt;
		printf(&amp;quot;file non vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
		write(fd, &amp;amp;fine, 0);&lt;br /&gt;
	} else printf(&amp;quot;file vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
&lt;br /&gt;
	//printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
	printf(&amp;quot;Open().\n&amp;quot;);&lt;br /&gt;
	while((c = getchar()) != EOF &amp;amp;&amp;amp; index &amp;lt; MAX_CHAR){&lt;br /&gt;
		arr[index] = c;&lt;br /&gt;
		index++;&lt;br /&gt;
	}&lt;br /&gt;
	//printf(&amp;quot;sizeof arr: %d\n&amp;quot;, sizeof(arr));&lt;br /&gt;
	write(fd, &amp;amp;arr, index);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
segnali + fork&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pty.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utmp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
&lt;br /&gt;
sigset_t usr12mask;&lt;br /&gt;
sigset_t usr1mask;&lt;br /&gt;
int status;&lt;br /&gt;
int fd, fdout;&lt;br /&gt;
char name[80];&lt;br /&gt;
static int bit;&lt;br /&gt;
char *ar[2] = {&amp;quot;bash&amp;quot;, NULL};&lt;br /&gt;
&lt;br /&gt;
void usr12action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	if (num == SIGCHLD)&lt;br /&gt;
		bit=-1;&lt;br /&gt;
	else {&lt;br /&gt;
		bit = (num == SIGUSR2);&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void usr1action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char_to_bin(unsigned char x, void *rec){&lt;br /&gt;
	int i;&lt;br /&gt;
	pid_t *r = rec;&lt;br /&gt;
&lt;br /&gt;
	for(i=7; i&amp;gt;=0; i--){&lt;br /&gt;
		char f = x &amp;gt;&amp;gt; i &amp;amp; 1;&lt;br /&gt;
		kill(*r,f?SIGUSR2:SIGUSR1);&lt;br /&gt;
		sigsuspend(&amp;amp;usr1mask);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void *v)&lt;br /&gt;
{&lt;br /&gt;
	sigsuspend(&amp;amp;usr12mask);&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bin2char(int (*f)(void *opaque), void *opaque) {&lt;br /&gt;
	int i;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (i=c=0; i&amp;lt;8; i++) {&lt;br /&gt;
		int n=f(opaque);&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return -1;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			static struct sigaction sa={&lt;br /&gt;
				.sa_sigaction=usr12action,&lt;br /&gt;
				.sa_flags=SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;,getpid());&lt;br /&gt;
&lt;br /&gt;
			sigfillset(&amp;amp;usr12mask);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGINT);&lt;br /&gt;
			sigprocmask(SIG_SETMASK,&amp;amp;usr12mask,NULL);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR2);&lt;br /&gt;
			sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGUSR2,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGCHLD,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c=bin2char(readbit,stdin)) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
			if (waitpid(pid, &amp;amp;status, 0) != pid)  status = -1;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			char *path;&lt;br /&gt;
			char *sppid;&lt;br /&gt;
			pid_t ppid=getppid();&lt;br /&gt;
			asprintf(&amp;amp;path,&amp;quot;/proc/%d/exe&amp;quot;,ppid);&lt;br /&gt;
			asprintf(&amp;amp;sppid,&amp;quot;%d&amp;quot;,ppid);&lt;br /&gt;
			execl(&amp;quot;/usr/bin/xterm&amp;quot;, &amp;quot;xterm&amp;quot;, &amp;quot;-e&amp;quot;, path, sppid, (void *) 0);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		unsigned char buf[BUFSIZE];&lt;br /&gt;
		unsigned char *s;&lt;br /&gt;
		pid_t receiver=atoi(argv[1]);&lt;br /&gt;
&lt;br /&gt;
		static struct sigaction sa={.sa_sigaction=usr1action};&lt;br /&gt;
		sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		sigfillset(&amp;amp;usr1mask);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGINT);&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;usr1mask,NULL);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGUSR1);&lt;br /&gt;
		if (argc == 2){&lt;br /&gt;
			while ((s=fgets(buf,BUFSIZE,stdin))!=NULL){&lt;br /&gt;
				while (*s){&lt;br /&gt;
					char_to_bin(*s++, &amp;amp;receiver);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
il programma in questione &amp;quot;unisce&amp;quot; di fatto i due programmi sigsend e sigrec.&lt;br /&gt;
l'idea è quella che venga lanciato un unico processo e aprire un nuovo terminale dove contiunare l'esecuzione del figlio creato attraverso la fork.&lt;br /&gt;
Possiamo quindi sfruttare il fatto che i due processi (essendo padre e figlio) conoscono i rispettivi pid e quindi automatizzare questa parte senza fornire alcun pid in input.&lt;br /&gt;
è possibile anche fornire un pid come argomento per comunicare con processi diversi.&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 (Fork del programma 2 di ([[User:Simone|Simone]]) )==&lt;br /&gt;
Sono state effettuate delle piccole modifiche rispetto al programma 2 e inoltre sono stati aggiunti dei commenti per rendere più intuitivo e leggibile il codice.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
sigset_t receiverMask;&lt;br /&gt;
sigset_t senderMask;&lt;br /&gt;
static int bit;&lt;br /&gt;
&lt;br /&gt;
void receiverAction(int num, siginfo_t *info, void *useless) { &lt;br /&gt;
	if (num == SIGCHLD)	// Se il processo figlio del ricevente è terminato&lt;br /&gt;
		bit = EOF;&lt;br /&gt;
	else{&lt;br /&gt;
		bit = (num == SIGUSR2);		// Codifico 1 con il segnale SIGUSR2 e 0 con SIGUSR1&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);	// Invio il segnale SIGUSR1 al mittente&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void senderAction(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void write_bin(unsigned char x, pid_t *recv){	/* Funzione che riguarda il mittente */&lt;br /&gt;
	unsigned int i;&lt;br /&gt;
	for(i=0x80; i&amp;gt;0; i&amp;gt;&amp;gt;=1){	// Parto da 10000000, man mano shifto a destra, 01000000, 00100000 ecc ecc, fino a 00000000&lt;br /&gt;
		kill(*recv, (x &amp;amp; i) ? SIGUSR2 : SIGUSR1);	// Invio segnale al ricevente&lt;br /&gt;
		sigsuspend(&amp;amp;senderMask);			// Attendo segnale di ritorno&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void){&lt;br /&gt;
	sigsuspend(&amp;amp;receiverMask);     // Sospende il processo e attende un segnale&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int read_char(){	/* Funzione che riguarda il ricevente */&lt;br /&gt;
	int i, c;&lt;br /&gt;
	for (i = c = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
		int n = readbit();&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return EOF;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){	/* PROCESSO PADRE (PROCESSO RICEVENTE) */&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Il valore di sa_flag permette di specificare vari aspetti del comportamento di sigaction:&lt;br /&gt;
			 * SA_SIGINFO specifica che si vuole usare un gestore in forma estesa usando sa_sigaction al&lt;br /&gt;
			 * posto di sa_handler. Il valore di sa_sigaction specifica la funzione da chiamare, permettendo&lt;br /&gt;
			 * di usare un gestore piu complesso, in grado di ricevere informazioni piu dettagliate dal&lt;br /&gt;
			 * sistema, attraverso la struttura siginfo_t&lt;br /&gt;
			 */&lt;br /&gt;
			struct sigaction sa = {&lt;br /&gt;
				.sa_sigaction = receiverAction,&lt;br /&gt;
				.sa_flags = SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;, getpid());&lt;br /&gt;
&lt;br /&gt;
			/* Inserisci tutti i segnali nell'insieme receiverMask */&lt;br /&gt;
			sigfillset(&amp;amp;receiverMask);&lt;br /&gt;
&lt;br /&gt;
			/* Elimina il segnale SIGINT dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGINT);&lt;br /&gt;
&lt;br /&gt;
			/* Setta la maschera dei segnali del processo con l'insieme receiverMask.&lt;br /&gt;
			 * Il valore NULL indica che la maschera attuale del processo non verrà salvata. */&lt;br /&gt;
			sigprocmask(SIG_SETMASK, &amp;amp;receiverMask, NULL);&lt;br /&gt;
			&lt;br /&gt;
			/* Elimina il segnale SIGCHLD, SIGUSR1 e SIGUSR2 dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR2);&lt;br /&gt;
			&lt;br /&gt;
			/* Setta l'azione sa per i segnali SIGUSR1, SIGUSR2 e SIGCHLD. &lt;br /&gt;
			 * Il valore NULL indica che l’azione corrente non viene restituita indietro. */&lt;br /&gt;
			sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGUSR2, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGCHLD, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c = read_char()) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
		&lt;br /&gt;
		}&lt;br /&gt;
		else if(pid == 0){	// PROCESSO FIGLIO&lt;br /&gt;
			char *cmd;&lt;br /&gt;
			pid_t ppid = getppid();	/* PID del processo padre (ricevente) */&lt;br /&gt;
&lt;br /&gt;
                        /* Avvio un altro terminale eseguendo lo stesso programma con parametri di input */&lt;br /&gt;
			asprintf(&amp;amp;cmd, &amp;quot;xterm -e /proc/%d/exe %d&amp;quot;, ppid, ppid);	&lt;br /&gt;
			system(cmd);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
		else{	// Errore Fork&lt;br /&gt;
			fprintf(stderr, &amp;quot;Errore fork&amp;quot;);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {	/* PROCESSO MITTENTE */&lt;br /&gt;
		unsigned char buf[BUFSIZE], *read;&lt;br /&gt;
		pid_t receiver = atoi(argv[1]);	   // Pid del ricevente&lt;br /&gt;
		&lt;br /&gt;
		/* Setto una banale azione (usr1action) alla ricezione del segnale SIGUSR1*/&lt;br /&gt;
		struct sigaction sa = {.sa_sigaction = senderAction}; &lt;br /&gt;
		sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		&lt;br /&gt;
		sigfillset(&amp;amp;senderMask);		        // Inserisco tutti i segnali nell'insieme senderMask&lt;br /&gt;
		sigdelset(&amp;amp;senderMask, SIGINT); 		// e cancello dall'insieme il segnale SIGINT.&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;senderMask,NULL);	// Setto la maschera creata per il processo corrente, senza salvare la precedente.&lt;br /&gt;
		sigdelset(&amp;amp;senderMask,SIGUSR1);			// Elimino il segnale SIGUSR1 dall'insieme.&lt;br /&gt;
		if (argc == 2){					// Se i paramentri in input sono 2&lt;br /&gt;
			while ((read = fgets(buf,BUFSIZE,stdin)) != NULL){     // Leggo dallo stdin&lt;br /&gt;
				while (*read)				       // Leggo tutta la stringa&lt;br /&gt;
					write_bin(*read++, &amp;amp;receiver);	       // Invio ogni singolo carattere della stringa al ricevente&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= programma 5 =&lt;br /&gt;
==Secret channel with inotify==&lt;br /&gt;
Stavo leggendo sul libro che e' possibile creare un canale di comunicazione segreto praticamente con ogni cosa all'interno di un sistema UNIX. In particolare mi ha interessato il caso di creare un canale mono direzionale tramite l'apertura dei file in lettura o scrittura e ho voluto provare a implementarne uno. Questi canali sono quasi impossibili da scovare per un amministratore di sistema e potrebbero permettere lo scambio di informazioni illecite. &lt;br /&gt;
Una cosa interessante e' che a quanto pare il kernel ha bisogno di qualche millisecondo per eseguire la inotify e che una precedente implementazione senza delay portava all'arrivo di messaggi sbagliati.&lt;br /&gt;
&lt;br /&gt;
===Server===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void printChar(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        char c;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1)&lt;br /&gt;
                        buffer[i]= '1';&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        c = strtol(buffer, 0, 2);&lt;br /&gt;
        printf(&amp;quot;%c&amp;quot;, c);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void handle_events (int fd, int wd, char *bin_message,int *current_bit){&lt;br /&gt;
        char buf [4096]&lt;br /&gt;
        __attribute__ ((aligned(__alignof__(struct inotify_event))));&lt;br /&gt;
        const struct inotify_event *event;&lt;br /&gt;
        int i;&lt;br /&gt;
        ssize_t len;&lt;br /&gt;
        char *ptr;&lt;br /&gt;
&lt;br /&gt;
        //loop while inotify events can be read from the fd&lt;br /&gt;
        for (;;){&lt;br /&gt;
                len = read (fd, buf, sizeof (buf));&lt;br /&gt;
                if (len == -1 &amp;amp;&amp;amp; errno != EAGAIN){&lt;br /&gt;
                        perror (&amp;quot;read&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                //if the read returns with the errono EAGAIN exit from the loop&lt;br /&gt;
                if (len &amp;lt;= 0)&lt;br /&gt;
                        break;&lt;br /&gt;
                //loop between all events in the buffer&lt;br /&gt;
                for (ptr = buf; ptr &amp;lt; buf + len;&lt;br /&gt;
                                ptr += sizeof(struct inotify_event) + event-&amp;gt;len){&lt;br /&gt;
                        event = (const struct inotify_event *) ptr;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_NOWRITE){&lt;br /&gt;
                                //received 1&lt;br /&gt;
&lt;br /&gt;
                                *bin_message |= 0x01;&lt;br /&gt;
                        }&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_WRITE){&lt;br /&gt;
&lt;br /&gt;
                                //received 0&lt;br /&gt;
                                //do nothing to leave 0&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        &lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void main () {&lt;br /&gt;
        char buf;&lt;br /&gt;
        int fd;&lt;br /&gt;
        int wd;&lt;br /&gt;
        struct pollfd fds [2];&lt;br /&gt;
        int nfds;&lt;br /&gt;
        int poll_num;&lt;br /&gt;
        unsigned char message_str [4096] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int count = 0;&lt;br /&gt;
        int bit_wrote = 0;&lt;br /&gt;
         &lt;br /&gt;
        char path [100] = &amp;quot;/inofify/watched&amp;quot;;&lt;br /&gt;
        int t;&lt;br /&gt;
&lt;br /&gt;
        //create the file descriptor where inotify events has to be read&lt;br /&gt;
        fd = inotify_init1(IN_NONBLOCK);&lt;br /&gt;
        if (fd == -1) {&lt;br /&gt;
                perror(&amp;quot;inotify_init1&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        wd = inotify_add_watch (fd, path, IN_CLOSE_NOWRITE | IN_CLOSE_WRITE);&lt;br /&gt;
&lt;br /&gt;
        if (wd == -1 ){&lt;br /&gt;
                fprintf (stderr, &amp;quot;Cannot watch '%s' \n&amp;quot;, path);&lt;br /&gt;
                perror (&amp;quot;inotify_add_watch&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //prepare for the polling on the fd&lt;br /&gt;
&lt;br /&gt;
        nfds = 2;&lt;br /&gt;
        fds[0].fd = STDIN_FILENO;&lt;br /&gt;
        fds[0].events = POLLIN;&lt;br /&gt;
        fds[1].fd = fd;&lt;br /&gt;
        fds[1].events = POLLIN;&lt;br /&gt;
&lt;br /&gt;
        printf (&amp;quot;Listening for events... Press ENTER to terminate and show the message\n&amp;quot;);&lt;br /&gt;
        while (1){&lt;br /&gt;
&lt;br /&gt;
                poll_num = poll(fds,nfds, -1);&lt;br /&gt;
                if (poll_num == -1){&lt;br /&gt;
                        if (errno == EINTR)&lt;br /&gt;
                                continue;&lt;br /&gt;
                        perror (&amp;quot;poll&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                if (poll_num &amp;gt; 0){&lt;br /&gt;
                        if (fds[0].revents &amp;amp; POLLIN){&lt;br /&gt;
&lt;br /&gt;
                                //exit on ENTER key pressed emptying the stdin&lt;br /&gt;
                                while (read (STDIN_FILENO,&amp;amp;buf,1) &amp;gt; 0 &amp;amp;&amp;amp; buf != '\n') continue;&lt;br /&gt;
                                break;&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                        }&lt;br /&gt;
                        //notify an event occurred&lt;br /&gt;
                        if (fds[1].revents &amp;amp; POLLIN ){&lt;br /&gt;
                                if (bit_wrote &amp;lt; 8){&lt;br /&gt;
                                        printf(&amp;quot;..&amp;quot;);&lt;br /&gt;
                                        fflush(stdout);&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                        if (bit_wrote &amp;lt; 7){&lt;br /&gt;
                                                message_str[count] = message_str[count] &amp;lt;&amp;lt; 0x01;&lt;br /&gt;
                                        }&lt;br /&gt;
&lt;br /&gt;
                                }&lt;br /&gt;
                                else {&lt;br /&gt;
                                        bit_wrote = 0;&lt;br /&gt;
                                        count += 1;&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                }&lt;br /&gt;
                                bit_wrote += 1;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**********MESSAGE***********\n&amp;quot;);&lt;br /&gt;
        t = 0;&lt;br /&gt;
        while (t &amp;lt;= count ){&lt;br /&gt;
&lt;br /&gt;
                printChar(message_str[t]);&lt;br /&gt;
                t += 1;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**************************\n&amp;quot;);&lt;br /&gt;
        printf(&amp;quot;\nClosing...\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        exit(EXIT_SUCCESS);&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Client=== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void chat(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        int fd;&lt;br /&gt;
        char path [] = &amp;quot;watched&amp;quot;;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        const struct timespec timer = {&lt;br /&gt;
                .tv_sec = 0,&lt;br /&gt;
                .tv_nsec = 500000&lt;br /&gt;
        };&lt;br /&gt;
        struct timespec s;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1){&lt;br /&gt;
&lt;br /&gt;
                        buffer[i] = '1';&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        for (a = 0; a &amp;lt; 8; a++) {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                if (buffer[a] == '0'){&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_WRONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                else{&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_RDONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                nanosleep(&amp;amp;timer,&amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
void main (){&lt;br /&gt;
        char message[1024] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int bit_message;&lt;br /&gt;
        int len = 0;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Type in \n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        fgets(message,100,stdin);&lt;br /&gt;
        printf(&amp;quot;You typed: %s&amp;quot;, message);&lt;br /&gt;
&lt;br /&gt;
        len = (unsigned)strlen(message);&lt;br /&gt;
        while (i &amp;lt; len -1){&lt;br /&gt;
                chat(message[i]);&lt;br /&gt;
                i++;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alessio Trivisonno&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1346</id>
		<title>Esercizi con System Call</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1346"/>
		<updated>2016-04-26T14:26:29Z</updated>

		<summary type="html">&lt;p&gt;Aletri: /* Client */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi contengono esempi di uso delle System-Call.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:03, 2 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
Il gatto di Schr&amp;amp;ouml;dinger: Fork e' vero o falso?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
  if (fork())&lt;br /&gt;
    printf(&amp;quot;fork is true\n&amp;quot;);&lt;br /&gt;
  else&lt;br /&gt;
    printf(&amp;quot;fork is false\n&amp;quot;);&lt;br /&gt;
  usleep(100000);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
il programma stampa entrambi i risultati perché la system call fork() crea un processo figlio identico al padre, questa system call ha come valore di ritorno al thread padre il pid del processo figlio (che essendo diverso da 0 è true) e al thread figlio ritorna 0, quindi il processo padre riceve un valore diverso da 0 (pid del figlio) e stampa true, mentre il processo figlio riceve 0, non entra nel if e stampa, ovviamente false.&lt;br /&gt;
&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
Open() Write() Read()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
/*IL PROGRAMMA APRE UN FILE SUL QUALE FA DELLE OPERAZIONI DI LETTURA E SCRITTURA*/&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_CHAR 100000&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	&lt;br /&gt;
	int fd, c, n_read;&lt;br /&gt;
	int fine = EOF;&lt;br /&gt;
        int index = 0;&lt;br /&gt;
	char arr[MAX_CHAR];&lt;br /&gt;
	char c_arr_read[MAX_CHAR];&lt;br /&gt;
	const char *path = //inserisci qui il percorso del file che vuoi aprire, se il file specificato non esiste, la open fallisce e il &lt;br /&gt;
                           //programma termina con un codice di errore&lt;br /&gt;
	fd = open(path, O_RDWR);&lt;br /&gt;
&lt;br /&gt;
	if(fd == -1){&lt;br /&gt;
		printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
		printf(&amp;quot;Open failed, Err: %d\n&amp;quot;, errno);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	if( (n_read = read(fd, &amp;amp;c_arr_read, MAX_CHAR)) &amp;gt; 0 ) {&lt;br /&gt;
		printf(&amp;quot;file non vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
		write(fd, &amp;amp;fine, 0);&lt;br /&gt;
	} else printf(&amp;quot;file vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
&lt;br /&gt;
	//printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
	printf(&amp;quot;Open().\n&amp;quot;);&lt;br /&gt;
	while((c = getchar()) != EOF &amp;amp;&amp;amp; index &amp;lt; MAX_CHAR){&lt;br /&gt;
		arr[index] = c;&lt;br /&gt;
		index++;&lt;br /&gt;
	}&lt;br /&gt;
	//printf(&amp;quot;sizeof arr: %d\n&amp;quot;, sizeof(arr));&lt;br /&gt;
	write(fd, &amp;amp;arr, index);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
segnali + fork&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pty.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utmp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
&lt;br /&gt;
sigset_t usr12mask;&lt;br /&gt;
sigset_t usr1mask;&lt;br /&gt;
int status;&lt;br /&gt;
int fd, fdout;&lt;br /&gt;
char name[80];&lt;br /&gt;
static int bit;&lt;br /&gt;
char *ar[2] = {&amp;quot;bash&amp;quot;, NULL};&lt;br /&gt;
&lt;br /&gt;
void usr12action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	if (num == SIGCHLD)&lt;br /&gt;
		bit=-1;&lt;br /&gt;
	else {&lt;br /&gt;
		bit = (num == SIGUSR2);&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void usr1action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char_to_bin(unsigned char x, void *rec){&lt;br /&gt;
	int i;&lt;br /&gt;
	pid_t *r = rec;&lt;br /&gt;
&lt;br /&gt;
	for(i=7; i&amp;gt;=0; i--){&lt;br /&gt;
		char f = x &amp;gt;&amp;gt; i &amp;amp; 1;&lt;br /&gt;
		kill(*r,f?SIGUSR2:SIGUSR1);&lt;br /&gt;
		sigsuspend(&amp;amp;usr1mask);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void *v)&lt;br /&gt;
{&lt;br /&gt;
	sigsuspend(&amp;amp;usr12mask);&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bin2char(int (*f)(void *opaque), void *opaque) {&lt;br /&gt;
	int i;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (i=c=0; i&amp;lt;8; i++) {&lt;br /&gt;
		int n=f(opaque);&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return -1;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			static struct sigaction sa={&lt;br /&gt;
				.sa_sigaction=usr12action,&lt;br /&gt;
				.sa_flags=SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;,getpid());&lt;br /&gt;
&lt;br /&gt;
			sigfillset(&amp;amp;usr12mask);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGINT);&lt;br /&gt;
			sigprocmask(SIG_SETMASK,&amp;amp;usr12mask,NULL);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR2);&lt;br /&gt;
			sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGUSR2,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGCHLD,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c=bin2char(readbit,stdin)) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
			if (waitpid(pid, &amp;amp;status, 0) != pid)  status = -1;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			char *path;&lt;br /&gt;
			char *sppid;&lt;br /&gt;
			pid_t ppid=getppid();&lt;br /&gt;
			asprintf(&amp;amp;path,&amp;quot;/proc/%d/exe&amp;quot;,ppid);&lt;br /&gt;
			asprintf(&amp;amp;sppid,&amp;quot;%d&amp;quot;,ppid);&lt;br /&gt;
			execl(&amp;quot;/usr/bin/xterm&amp;quot;, &amp;quot;xterm&amp;quot;, &amp;quot;-e&amp;quot;, path, sppid, (void *) 0);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		unsigned char buf[BUFSIZE];&lt;br /&gt;
		unsigned char *s;&lt;br /&gt;
		pid_t receiver=atoi(argv[1]);&lt;br /&gt;
&lt;br /&gt;
		static struct sigaction sa={.sa_sigaction=usr1action};&lt;br /&gt;
		sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		sigfillset(&amp;amp;usr1mask);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGINT);&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;usr1mask,NULL);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGUSR1);&lt;br /&gt;
		if (argc == 2){&lt;br /&gt;
			while ((s=fgets(buf,BUFSIZE,stdin))!=NULL){&lt;br /&gt;
				while (*s){&lt;br /&gt;
					char_to_bin(*s++, &amp;amp;receiver);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
il programma in questione &amp;quot;unisce&amp;quot; di fatto i due programmi sigsend e sigrec.&lt;br /&gt;
l'idea è quella che venga lanciato un unico processo e aprire un nuovo terminale dove contiunare l'esecuzione del figlio creato attraverso la fork.&lt;br /&gt;
Possiamo quindi sfruttare il fatto che i due processi (essendo padre e figlio) conoscono i rispettivi pid e quindi automatizzare questa parte senza fornire alcun pid in input.&lt;br /&gt;
è possibile anche fornire un pid come argomento per comunicare con processi diversi.&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 (Fork del programma 2 di ([[User:Simone|Simone]]) )==&lt;br /&gt;
Sono state effettuate delle piccole modifiche rispetto al programma 2 e inoltre sono stati aggiunti dei commenti per rendere più intuitivo e leggibile il codice.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
sigset_t receiverMask;&lt;br /&gt;
sigset_t senderMask;&lt;br /&gt;
static int bit;&lt;br /&gt;
&lt;br /&gt;
void receiverAction(int num, siginfo_t *info, void *useless) { &lt;br /&gt;
	if (num == SIGCHLD)	// Se il processo figlio del ricevente è terminato&lt;br /&gt;
		bit = EOF;&lt;br /&gt;
	else{&lt;br /&gt;
		bit = (num == SIGUSR2);		// Codifico 1 con il segnale SIGUSR2 e 0 con SIGUSR1&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);	// Invio il segnale SIGUSR1 al mittente&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void senderAction(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void write_bin(unsigned char x, pid_t *recv){	/* Funzione che riguarda il mittente */&lt;br /&gt;
	unsigned int i;&lt;br /&gt;
	for(i=0x80; i&amp;gt;0; i&amp;gt;&amp;gt;=1){	// Parto da 10000000, man mano shifto a destra, 01000000, 00100000 ecc ecc, fino a 00000000&lt;br /&gt;
		kill(*recv, (x &amp;amp; i) ? SIGUSR2 : SIGUSR1);	// Invio segnale al ricevente&lt;br /&gt;
		sigsuspend(&amp;amp;senderMask);			// Attendo segnale di ritorno&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void){&lt;br /&gt;
	sigsuspend(&amp;amp;receiverMask);     // Sospende il processo e attende un segnale&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int read_char(){	/* Funzione che riguarda il ricevente */&lt;br /&gt;
	int i, c;&lt;br /&gt;
	for (i = c = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
		int n = readbit();&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return EOF;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){	/* PROCESSO PADRE (PROCESSO RICEVENTE) */&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Il valore di sa_flag permette di specificare vari aspetti del comportamento di sigaction:&lt;br /&gt;
			 * SA_SIGINFO specifica che si vuole usare un gestore in forma estesa usando sa_sigaction al&lt;br /&gt;
			 * posto di sa_handler. Il valore di sa_sigaction specifica la funzione da chiamare, permettendo&lt;br /&gt;
			 * di usare un gestore piu complesso, in grado di ricevere informazioni piu dettagliate dal&lt;br /&gt;
			 * sistema, attraverso la struttura siginfo_t&lt;br /&gt;
			 */&lt;br /&gt;
			struct sigaction sa = {&lt;br /&gt;
				.sa_sigaction = receiverAction,&lt;br /&gt;
				.sa_flags = SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;, getpid());&lt;br /&gt;
&lt;br /&gt;
			/* Inserisci tutti i segnali nell'insieme receiverMask */&lt;br /&gt;
			sigfillset(&amp;amp;receiverMask);&lt;br /&gt;
&lt;br /&gt;
			/* Elimina il segnale SIGINT dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGINT);&lt;br /&gt;
&lt;br /&gt;
			/* Setta la maschera dei segnali del processo con l'insieme receiverMask.&lt;br /&gt;
			 * Il valore NULL indica che la maschera attuale del processo non verrà salvata. */&lt;br /&gt;
			sigprocmask(SIG_SETMASK, &amp;amp;receiverMask, NULL);&lt;br /&gt;
			&lt;br /&gt;
			/* Elimina il segnale SIGCHLD, SIGUSR1 e SIGUSR2 dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR2);&lt;br /&gt;
			&lt;br /&gt;
			/* Setta l'azione sa per i segnali SIGUSR1, SIGUSR2 e SIGCHLD. &lt;br /&gt;
			 * Il valore NULL indica che l’azione corrente non viene restituita indietro. */&lt;br /&gt;
			sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGUSR2, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGCHLD, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c = read_char()) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
		&lt;br /&gt;
		}&lt;br /&gt;
		else if(pid == 0){	// PROCESSO FIGLIO&lt;br /&gt;
			char *cmd;&lt;br /&gt;
			pid_t ppid = getppid();	/* PID del processo padre (ricevente) */&lt;br /&gt;
&lt;br /&gt;
                        /* Avvio un altro terminale eseguendo lo stesso programma con parametri di input */&lt;br /&gt;
			asprintf(&amp;amp;cmd, &amp;quot;xterm -e /proc/%d/exe %d&amp;quot;, ppid, ppid);	&lt;br /&gt;
			system(cmd);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
		else{	// Errore Fork&lt;br /&gt;
			fprintf(stderr, &amp;quot;Errore fork&amp;quot;);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {	/* PROCESSO MITTENTE */&lt;br /&gt;
		unsigned char buf[BUFSIZE], *read;&lt;br /&gt;
		pid_t receiver = atoi(argv[1]);	   // Pid del ricevente&lt;br /&gt;
		&lt;br /&gt;
		/* Setto una banale azione (usr1action) alla ricezione del segnale SIGUSR1*/&lt;br /&gt;
		struct sigaction sa = {.sa_sigaction = senderAction}; &lt;br /&gt;
		sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		&lt;br /&gt;
		sigfillset(&amp;amp;senderMask);		        // Inserisco tutti i segnali nell'insieme senderMask&lt;br /&gt;
		sigdelset(&amp;amp;senderMask, SIGINT); 		// e cancello dall'insieme il segnale SIGINT.&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;senderMask,NULL);	// Setto la maschera creata per il processo corrente, senza salvare la precedente.&lt;br /&gt;
		sigdelset(&amp;amp;senderMask,SIGUSR1);			// Elimino il segnale SIGUSR1 dall'insieme.&lt;br /&gt;
		if (argc == 2){					// Se i paramentri in input sono 2&lt;br /&gt;
			while ((read = fgets(buf,BUFSIZE,stdin)) != NULL){     // Leggo dallo stdin&lt;br /&gt;
				while (*read)				       // Leggo tutta la stringa&lt;br /&gt;
					write_bin(*read++, &amp;amp;receiver);	       // Invio ogni singolo carattere della stringa al ricevente&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= programma 5 =&lt;br /&gt;
==Secret channel with inotify==&lt;br /&gt;
Stavo leggendo sul libro che e' possibile creare un canale di comunicazione segreto praticamente con ogni cosa all'interno di un sistema UNIX. In particolare mi ha interessato il caso di creare un canale mono direzionale tramite l'apertura dei file in lettura o scrittura e ho voluto provare a implementarne uno. Questi canali sono quasi impossibili da scovare per un amministratore di sistema e potrebbero permettere lo scambio di informazioni illecite. &lt;br /&gt;
Una cosa interessante e' che a quanto pare il kernel ha bisogno di qualche millisecondo per eseguire la inotify e che una precedente implementazione senza delay portava all'arrivo di messaggi sbagliati.&lt;br /&gt;
&lt;br /&gt;
===Server===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void printChar(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        char c;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1)&lt;br /&gt;
                        buffer[i]= '1';&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        c = strtol(buffer, 0, 2);&lt;br /&gt;
        printf(&amp;quot;%c&amp;quot;, c);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void handle_events (int fd, int wd, char *bin_message,int *current_bit){&lt;br /&gt;
        char buf [4096]&lt;br /&gt;
        __attribute__ ((aligned(__alignof__(struct inotify_event))));&lt;br /&gt;
        const struct inotify_event *event;&lt;br /&gt;
        int i;&lt;br /&gt;
        ssize_t len;&lt;br /&gt;
        char *ptr;&lt;br /&gt;
&lt;br /&gt;
        //loop while inotify events can be read from the fd&lt;br /&gt;
        for (;;){&lt;br /&gt;
                len = read (fd, buf, sizeof (buf));&lt;br /&gt;
                if (len == -1 &amp;amp;&amp;amp; errno != EAGAIN){&lt;br /&gt;
                        perror (&amp;quot;read&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                //if the read returns with the errono EAGAIN exit from the loop&lt;br /&gt;
                if (len &amp;lt;= 0)&lt;br /&gt;
                        break;&lt;br /&gt;
                //loop between all events in the buffer&lt;br /&gt;
                for (ptr = buf; ptr &amp;lt; buf + len;&lt;br /&gt;
                                ptr += sizeof(struct inotify_event) + event-&amp;gt;len){&lt;br /&gt;
                        event = (const struct inotify_event *) ptr;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_NOWRITE){&lt;br /&gt;
                                //received 1&lt;br /&gt;
&lt;br /&gt;
                                *bin_message |= 0x01;&lt;br /&gt;
                        }&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_WRITE){&lt;br /&gt;
&lt;br /&gt;
                                //received 0&lt;br /&gt;
                                //do nothing to leave 0&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        &lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void main () {&lt;br /&gt;
        char buf;&lt;br /&gt;
        int fd;&lt;br /&gt;
        int wd;&lt;br /&gt;
        struct pollfd fds [2];&lt;br /&gt;
        int nfds;&lt;br /&gt;
        int poll_num;&lt;br /&gt;
        /*char message = 0;*/&lt;br /&gt;
        unsigned char message_str [4096] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int count = 0;&lt;br /&gt;
        int bit_wrote = 0;&lt;br /&gt;
         &lt;br /&gt;
        char path [100] = &amp;quot;/inofify/watched&amp;quot;;&lt;br /&gt;
        int t;&lt;br /&gt;
&lt;br /&gt;
        //create the file descriptor where inotify events has to be read&lt;br /&gt;
        fd = inotify_init1(IN_NONBLOCK);&lt;br /&gt;
        if (fd == -1) {&lt;br /&gt;
                perror(&amp;quot;inotify_init1&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        wd = inotify_add_watch (fd, path, IN_CLOSE_NOWRITE | IN_CLOSE_WRITE);&lt;br /&gt;
&lt;br /&gt;
        if (wd == -1 ){&lt;br /&gt;
                fprintf (stderr, &amp;quot;Cannot watch '%s' \n&amp;quot;, path);&lt;br /&gt;
                perror (&amp;quot;inotify_add_watch&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //prepare for the polling on the fd&lt;br /&gt;
&lt;br /&gt;
        nfds = 2;&lt;br /&gt;
        fds[0].fd = STDIN_FILENO;&lt;br /&gt;
        fds[0].events = POLLIN;&lt;br /&gt;
        fds[1].fd = fd;&lt;br /&gt;
        fds[1].events = POLLIN;&lt;br /&gt;
&lt;br /&gt;
        printf (&amp;quot;Listening for events... Press ENTER to terminate and show the message\n&amp;quot;);&lt;br /&gt;
        while (1){&lt;br /&gt;
&lt;br /&gt;
                poll_num = poll(fds,nfds, -1);&lt;br /&gt;
                if (poll_num == -1){&lt;br /&gt;
                        if (errno == EINTR)&lt;br /&gt;
                                continue;&lt;br /&gt;
                        perror (&amp;quot;poll&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                if (poll_num &amp;gt; 0){&lt;br /&gt;
                        if (fds[0].revents &amp;amp; POLLIN){&lt;br /&gt;
&lt;br /&gt;
                                //exit on ENTER key pressed emptying the stdin&lt;br /&gt;
                                while (read (STDIN_FILENO,&amp;amp;buf,1) &amp;gt; 0 &amp;amp;&amp;amp; buf != '\n') continue;&lt;br /&gt;
                                break;&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                        }&lt;br /&gt;
                        //notify an event occurred&lt;br /&gt;
                        if (fds[1].revents &amp;amp; POLLIN ){&lt;br /&gt;
                                if (bit_wrote &amp;lt; 8){&lt;br /&gt;
                                        printf(&amp;quot;..&amp;quot;);&lt;br /&gt;
                                        fflush(stdout);&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                        if (bit_wrote &amp;lt; 7){&lt;br /&gt;
                                                message_str[count] = message_str[count] &amp;lt;&amp;lt; 0x01;&lt;br /&gt;
                                        }&lt;br /&gt;
&lt;br /&gt;
                                }&lt;br /&gt;
                                else {&lt;br /&gt;
                                        bit_wrote = 0;&lt;br /&gt;
                                        count += 1;&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                }&lt;br /&gt;
                                bit_wrote += 1;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**********MESSAGE***********\n&amp;quot;);&lt;br /&gt;
        t = 0;&lt;br /&gt;
        while (t &amp;lt;= count ){&lt;br /&gt;
&lt;br /&gt;
                printChar(message_str[t]);&lt;br /&gt;
                t += 1;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**************************\n&amp;quot;);&lt;br /&gt;
        printf(&amp;quot;\nClosing...\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        exit(EXIT_SUCCESS);&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Client=== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void chat(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        int fd;&lt;br /&gt;
        char path [] = &amp;quot;watched&amp;quot;;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        const struct timespec timer = {&lt;br /&gt;
                .tv_sec = 0,&lt;br /&gt;
                .tv_nsec = 500000&lt;br /&gt;
        };&lt;br /&gt;
        struct timespec s;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1){&lt;br /&gt;
&lt;br /&gt;
                        buffer[i] = '1';&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        for (a = 0; a &amp;lt; 8; a++) {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                if (buffer[a] == '0'){&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_WRONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                else{&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_RDONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                nanosleep(&amp;amp;timer,&amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
void main (){&lt;br /&gt;
        char message[1024] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int bit_message;&lt;br /&gt;
        int len = 0;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Type in \n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        fgets(message,100,stdin);&lt;br /&gt;
        printf(&amp;quot;You typed: %s&amp;quot;, message);&lt;br /&gt;
&lt;br /&gt;
        len = (unsigned)strlen(message);&lt;br /&gt;
        while (i &amp;lt; len -1){&lt;br /&gt;
                chat(message[i]);&lt;br /&gt;
                i++;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alessio Trivisonno&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1345</id>
		<title>Esercizi con System Call</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1345"/>
		<updated>2016-04-26T14:26:10Z</updated>

		<summary type="html">&lt;p&gt;Aletri: /* Client */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi contengono esempi di uso delle System-Call.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:03, 2 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
Il gatto di Schr&amp;amp;ouml;dinger: Fork e' vero o falso?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
  if (fork())&lt;br /&gt;
    printf(&amp;quot;fork is true\n&amp;quot;);&lt;br /&gt;
  else&lt;br /&gt;
    printf(&amp;quot;fork is false\n&amp;quot;);&lt;br /&gt;
  usleep(100000);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
il programma stampa entrambi i risultati perché la system call fork() crea un processo figlio identico al padre, questa system call ha come valore di ritorno al thread padre il pid del processo figlio (che essendo diverso da 0 è true) e al thread figlio ritorna 0, quindi il processo padre riceve un valore diverso da 0 (pid del figlio) e stampa true, mentre il processo figlio riceve 0, non entra nel if e stampa, ovviamente false.&lt;br /&gt;
&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
Open() Write() Read()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
/*IL PROGRAMMA APRE UN FILE SUL QUALE FA DELLE OPERAZIONI DI LETTURA E SCRITTURA*/&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_CHAR 100000&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	&lt;br /&gt;
	int fd, c, n_read;&lt;br /&gt;
	int fine = EOF;&lt;br /&gt;
        int index = 0;&lt;br /&gt;
	char arr[MAX_CHAR];&lt;br /&gt;
	char c_arr_read[MAX_CHAR];&lt;br /&gt;
	const char *path = //inserisci qui il percorso del file che vuoi aprire, se il file specificato non esiste, la open fallisce e il &lt;br /&gt;
                           //programma termina con un codice di errore&lt;br /&gt;
	fd = open(path, O_RDWR);&lt;br /&gt;
&lt;br /&gt;
	if(fd == -1){&lt;br /&gt;
		printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
		printf(&amp;quot;Open failed, Err: %d\n&amp;quot;, errno);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	if( (n_read = read(fd, &amp;amp;c_arr_read, MAX_CHAR)) &amp;gt; 0 ) {&lt;br /&gt;
		printf(&amp;quot;file non vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
		write(fd, &amp;amp;fine, 0);&lt;br /&gt;
	} else printf(&amp;quot;file vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
&lt;br /&gt;
	//printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
	printf(&amp;quot;Open().\n&amp;quot;);&lt;br /&gt;
	while((c = getchar()) != EOF &amp;amp;&amp;amp; index &amp;lt; MAX_CHAR){&lt;br /&gt;
		arr[index] = c;&lt;br /&gt;
		index++;&lt;br /&gt;
	}&lt;br /&gt;
	//printf(&amp;quot;sizeof arr: %d\n&amp;quot;, sizeof(arr));&lt;br /&gt;
	write(fd, &amp;amp;arr, index);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
segnali + fork&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pty.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utmp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
&lt;br /&gt;
sigset_t usr12mask;&lt;br /&gt;
sigset_t usr1mask;&lt;br /&gt;
int status;&lt;br /&gt;
int fd, fdout;&lt;br /&gt;
char name[80];&lt;br /&gt;
static int bit;&lt;br /&gt;
char *ar[2] = {&amp;quot;bash&amp;quot;, NULL};&lt;br /&gt;
&lt;br /&gt;
void usr12action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	if (num == SIGCHLD)&lt;br /&gt;
		bit=-1;&lt;br /&gt;
	else {&lt;br /&gt;
		bit = (num == SIGUSR2);&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void usr1action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char_to_bin(unsigned char x, void *rec){&lt;br /&gt;
	int i;&lt;br /&gt;
	pid_t *r = rec;&lt;br /&gt;
&lt;br /&gt;
	for(i=7; i&amp;gt;=0; i--){&lt;br /&gt;
		char f = x &amp;gt;&amp;gt; i &amp;amp; 1;&lt;br /&gt;
		kill(*r,f?SIGUSR2:SIGUSR1);&lt;br /&gt;
		sigsuspend(&amp;amp;usr1mask);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void *v)&lt;br /&gt;
{&lt;br /&gt;
	sigsuspend(&amp;amp;usr12mask);&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bin2char(int (*f)(void *opaque), void *opaque) {&lt;br /&gt;
	int i;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (i=c=0; i&amp;lt;8; i++) {&lt;br /&gt;
		int n=f(opaque);&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return -1;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			static struct sigaction sa={&lt;br /&gt;
				.sa_sigaction=usr12action,&lt;br /&gt;
				.sa_flags=SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;,getpid());&lt;br /&gt;
&lt;br /&gt;
			sigfillset(&amp;amp;usr12mask);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGINT);&lt;br /&gt;
			sigprocmask(SIG_SETMASK,&amp;amp;usr12mask,NULL);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR2);&lt;br /&gt;
			sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGUSR2,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGCHLD,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c=bin2char(readbit,stdin)) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
			if (waitpid(pid, &amp;amp;status, 0) != pid)  status = -1;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			char *path;&lt;br /&gt;
			char *sppid;&lt;br /&gt;
			pid_t ppid=getppid();&lt;br /&gt;
			asprintf(&amp;amp;path,&amp;quot;/proc/%d/exe&amp;quot;,ppid);&lt;br /&gt;
			asprintf(&amp;amp;sppid,&amp;quot;%d&amp;quot;,ppid);&lt;br /&gt;
			execl(&amp;quot;/usr/bin/xterm&amp;quot;, &amp;quot;xterm&amp;quot;, &amp;quot;-e&amp;quot;, path, sppid, (void *) 0);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		unsigned char buf[BUFSIZE];&lt;br /&gt;
		unsigned char *s;&lt;br /&gt;
		pid_t receiver=atoi(argv[1]);&lt;br /&gt;
&lt;br /&gt;
		static struct sigaction sa={.sa_sigaction=usr1action};&lt;br /&gt;
		sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		sigfillset(&amp;amp;usr1mask);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGINT);&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;usr1mask,NULL);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGUSR1);&lt;br /&gt;
		if (argc == 2){&lt;br /&gt;
			while ((s=fgets(buf,BUFSIZE,stdin))!=NULL){&lt;br /&gt;
				while (*s){&lt;br /&gt;
					char_to_bin(*s++, &amp;amp;receiver);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
il programma in questione &amp;quot;unisce&amp;quot; di fatto i due programmi sigsend e sigrec.&lt;br /&gt;
l'idea è quella che venga lanciato un unico processo e aprire un nuovo terminale dove contiunare l'esecuzione del figlio creato attraverso la fork.&lt;br /&gt;
Possiamo quindi sfruttare il fatto che i due processi (essendo padre e figlio) conoscono i rispettivi pid e quindi automatizzare questa parte senza fornire alcun pid in input.&lt;br /&gt;
è possibile anche fornire un pid come argomento per comunicare con processi diversi.&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 (Fork del programma 2 di ([[User:Simone|Simone]]) )==&lt;br /&gt;
Sono state effettuate delle piccole modifiche rispetto al programma 2 e inoltre sono stati aggiunti dei commenti per rendere più intuitivo e leggibile il codice.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
sigset_t receiverMask;&lt;br /&gt;
sigset_t senderMask;&lt;br /&gt;
static int bit;&lt;br /&gt;
&lt;br /&gt;
void receiverAction(int num, siginfo_t *info, void *useless) { &lt;br /&gt;
	if (num == SIGCHLD)	// Se il processo figlio del ricevente è terminato&lt;br /&gt;
		bit = EOF;&lt;br /&gt;
	else{&lt;br /&gt;
		bit = (num == SIGUSR2);		// Codifico 1 con il segnale SIGUSR2 e 0 con SIGUSR1&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);	// Invio il segnale SIGUSR1 al mittente&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void senderAction(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void write_bin(unsigned char x, pid_t *recv){	/* Funzione che riguarda il mittente */&lt;br /&gt;
	unsigned int i;&lt;br /&gt;
	for(i=0x80; i&amp;gt;0; i&amp;gt;&amp;gt;=1){	// Parto da 10000000, man mano shifto a destra, 01000000, 00100000 ecc ecc, fino a 00000000&lt;br /&gt;
		kill(*recv, (x &amp;amp; i) ? SIGUSR2 : SIGUSR1);	// Invio segnale al ricevente&lt;br /&gt;
		sigsuspend(&amp;amp;senderMask);			// Attendo segnale di ritorno&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void){&lt;br /&gt;
	sigsuspend(&amp;amp;receiverMask);     // Sospende il processo e attende un segnale&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int read_char(){	/* Funzione che riguarda il ricevente */&lt;br /&gt;
	int i, c;&lt;br /&gt;
	for (i = c = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
		int n = readbit();&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return EOF;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){	/* PROCESSO PADRE (PROCESSO RICEVENTE) */&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Il valore di sa_flag permette di specificare vari aspetti del comportamento di sigaction:&lt;br /&gt;
			 * SA_SIGINFO specifica che si vuole usare un gestore in forma estesa usando sa_sigaction al&lt;br /&gt;
			 * posto di sa_handler. Il valore di sa_sigaction specifica la funzione da chiamare, permettendo&lt;br /&gt;
			 * di usare un gestore piu complesso, in grado di ricevere informazioni piu dettagliate dal&lt;br /&gt;
			 * sistema, attraverso la struttura siginfo_t&lt;br /&gt;
			 */&lt;br /&gt;
			struct sigaction sa = {&lt;br /&gt;
				.sa_sigaction = receiverAction,&lt;br /&gt;
				.sa_flags = SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;, getpid());&lt;br /&gt;
&lt;br /&gt;
			/* Inserisci tutti i segnali nell'insieme receiverMask */&lt;br /&gt;
			sigfillset(&amp;amp;receiverMask);&lt;br /&gt;
&lt;br /&gt;
			/* Elimina il segnale SIGINT dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGINT);&lt;br /&gt;
&lt;br /&gt;
			/* Setta la maschera dei segnali del processo con l'insieme receiverMask.&lt;br /&gt;
			 * Il valore NULL indica che la maschera attuale del processo non verrà salvata. */&lt;br /&gt;
			sigprocmask(SIG_SETMASK, &amp;amp;receiverMask, NULL);&lt;br /&gt;
			&lt;br /&gt;
			/* Elimina il segnale SIGCHLD, SIGUSR1 e SIGUSR2 dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR2);&lt;br /&gt;
			&lt;br /&gt;
			/* Setta l'azione sa per i segnali SIGUSR1, SIGUSR2 e SIGCHLD. &lt;br /&gt;
			 * Il valore NULL indica che l’azione corrente non viene restituita indietro. */&lt;br /&gt;
			sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGUSR2, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGCHLD, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c = read_char()) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
		&lt;br /&gt;
		}&lt;br /&gt;
		else if(pid == 0){	// PROCESSO FIGLIO&lt;br /&gt;
			char *cmd;&lt;br /&gt;
			pid_t ppid = getppid();	/* PID del processo padre (ricevente) */&lt;br /&gt;
&lt;br /&gt;
                        /* Avvio un altro terminale eseguendo lo stesso programma con parametri di input */&lt;br /&gt;
			asprintf(&amp;amp;cmd, &amp;quot;xterm -e /proc/%d/exe %d&amp;quot;, ppid, ppid);	&lt;br /&gt;
			system(cmd);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
		else{	// Errore Fork&lt;br /&gt;
			fprintf(stderr, &amp;quot;Errore fork&amp;quot;);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {	/* PROCESSO MITTENTE */&lt;br /&gt;
		unsigned char buf[BUFSIZE], *read;&lt;br /&gt;
		pid_t receiver = atoi(argv[1]);	   // Pid del ricevente&lt;br /&gt;
		&lt;br /&gt;
		/* Setto una banale azione (usr1action) alla ricezione del segnale SIGUSR1*/&lt;br /&gt;
		struct sigaction sa = {.sa_sigaction = senderAction}; &lt;br /&gt;
		sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		&lt;br /&gt;
		sigfillset(&amp;amp;senderMask);		        // Inserisco tutti i segnali nell'insieme senderMask&lt;br /&gt;
		sigdelset(&amp;amp;senderMask, SIGINT); 		// e cancello dall'insieme il segnale SIGINT.&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;senderMask,NULL);	// Setto la maschera creata per il processo corrente, senza salvare la precedente.&lt;br /&gt;
		sigdelset(&amp;amp;senderMask,SIGUSR1);			// Elimino il segnale SIGUSR1 dall'insieme.&lt;br /&gt;
		if (argc == 2){					// Se i paramentri in input sono 2&lt;br /&gt;
			while ((read = fgets(buf,BUFSIZE,stdin)) != NULL){     // Leggo dallo stdin&lt;br /&gt;
				while (*read)				       // Leggo tutta la stringa&lt;br /&gt;
					write_bin(*read++, &amp;amp;receiver);	       // Invio ogni singolo carattere della stringa al ricevente&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= programma 5 =&lt;br /&gt;
==Secret channel with inotify==&lt;br /&gt;
Stavo leggendo sul libro che e' possibile creare un canale di comunicazione segreto praticamente con ogni cosa all'interno di un sistema UNIX. In particolare mi ha interessato il caso di creare un canale mono direzionale tramite l'apertura dei file in lettura o scrittura e ho voluto provare a implementarne uno. Questi canali sono quasi impossibili da scovare per un amministratore di sistema e potrebbero permettere lo scambio di informazioni illecite. &lt;br /&gt;
Una cosa interessante e' che a quanto pare il kernel ha bisogno di qualche millisecondo per eseguire la inotify e che una precedente implementazione senza delay portava all'arrivo di messaggi sbagliati.&lt;br /&gt;
&lt;br /&gt;
===Server===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void printChar(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        char c;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1)&lt;br /&gt;
                        buffer[i]= '1';&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        c = strtol(buffer, 0, 2);&lt;br /&gt;
        printf(&amp;quot;%c&amp;quot;, c);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void handle_events (int fd, int wd, char *bin_message,int *current_bit){&lt;br /&gt;
        char buf [4096]&lt;br /&gt;
        __attribute__ ((aligned(__alignof__(struct inotify_event))));&lt;br /&gt;
        const struct inotify_event *event;&lt;br /&gt;
        int i;&lt;br /&gt;
        ssize_t len;&lt;br /&gt;
        char *ptr;&lt;br /&gt;
&lt;br /&gt;
        //loop while inotify events can be read from the fd&lt;br /&gt;
        for (;;){&lt;br /&gt;
                len = read (fd, buf, sizeof (buf));&lt;br /&gt;
                if (len == -1 &amp;amp;&amp;amp; errno != EAGAIN){&lt;br /&gt;
                        perror (&amp;quot;read&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                //if the read returns with the errono EAGAIN exit from the loop&lt;br /&gt;
                if (len &amp;lt;= 0)&lt;br /&gt;
                        break;&lt;br /&gt;
                //loop between all events in the buffer&lt;br /&gt;
                for (ptr = buf; ptr &amp;lt; buf + len;&lt;br /&gt;
                                ptr += sizeof(struct inotify_event) + event-&amp;gt;len){&lt;br /&gt;
                        event = (const struct inotify_event *) ptr;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_NOWRITE){&lt;br /&gt;
                                //received 1&lt;br /&gt;
&lt;br /&gt;
                                *bin_message |= 0x01;&lt;br /&gt;
                        }&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_WRITE){&lt;br /&gt;
&lt;br /&gt;
                                //received 0&lt;br /&gt;
                                //do nothing to leave 0&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        &lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void main () {&lt;br /&gt;
        char buf;&lt;br /&gt;
        int fd;&lt;br /&gt;
        int wd;&lt;br /&gt;
        struct pollfd fds [2];&lt;br /&gt;
        int nfds;&lt;br /&gt;
        int poll_num;&lt;br /&gt;
        /*char message = 0;*/&lt;br /&gt;
        unsigned char message_str [4096] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int count = 0;&lt;br /&gt;
        int bit_wrote = 0;&lt;br /&gt;
         &lt;br /&gt;
        char path [100] = &amp;quot;/inofify/watched&amp;quot;;&lt;br /&gt;
        int t;&lt;br /&gt;
&lt;br /&gt;
        //create the file descriptor where inotify events has to be read&lt;br /&gt;
        fd = inotify_init1(IN_NONBLOCK);&lt;br /&gt;
        if (fd == -1) {&lt;br /&gt;
                perror(&amp;quot;inotify_init1&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        wd = inotify_add_watch (fd, path, IN_CLOSE_NOWRITE | IN_CLOSE_WRITE);&lt;br /&gt;
&lt;br /&gt;
        if (wd == -1 ){&lt;br /&gt;
                fprintf (stderr, &amp;quot;Cannot watch '%s' \n&amp;quot;, path);&lt;br /&gt;
                perror (&amp;quot;inotify_add_watch&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //prepare for the polling on the fd&lt;br /&gt;
&lt;br /&gt;
        nfds = 2;&lt;br /&gt;
        fds[0].fd = STDIN_FILENO;&lt;br /&gt;
        fds[0].events = POLLIN;&lt;br /&gt;
        fds[1].fd = fd;&lt;br /&gt;
        fds[1].events = POLLIN;&lt;br /&gt;
&lt;br /&gt;
        printf (&amp;quot;Listening for events... Press ENTER to terminate and show the message\n&amp;quot;);&lt;br /&gt;
        while (1){&lt;br /&gt;
&lt;br /&gt;
                poll_num = poll(fds,nfds, -1);&lt;br /&gt;
                if (poll_num == -1){&lt;br /&gt;
                        if (errno == EINTR)&lt;br /&gt;
                                continue;&lt;br /&gt;
                        perror (&amp;quot;poll&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                if (poll_num &amp;gt; 0){&lt;br /&gt;
                        if (fds[0].revents &amp;amp; POLLIN){&lt;br /&gt;
&lt;br /&gt;
                                //exit on ENTER key pressed emptying the stdin&lt;br /&gt;
                                while (read (STDIN_FILENO,&amp;amp;buf,1) &amp;gt; 0 &amp;amp;&amp;amp; buf != '\n') continue;&lt;br /&gt;
                                break;&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                        }&lt;br /&gt;
                        //notify an event occurred&lt;br /&gt;
                        if (fds[1].revents &amp;amp; POLLIN ){&lt;br /&gt;
                                if (bit_wrote &amp;lt; 8){&lt;br /&gt;
                                        printf(&amp;quot;..&amp;quot;);&lt;br /&gt;
                                        fflush(stdout);&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                        if (bit_wrote &amp;lt; 7){&lt;br /&gt;
                                                message_str[count] = message_str[count] &amp;lt;&amp;lt; 0x01;&lt;br /&gt;
                                        }&lt;br /&gt;
&lt;br /&gt;
                                }&lt;br /&gt;
                                else {&lt;br /&gt;
                                        bit_wrote = 0;&lt;br /&gt;
                                        count += 1;&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                }&lt;br /&gt;
                                bit_wrote += 1;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**********MESSAGE***********\n&amp;quot;);&lt;br /&gt;
        t = 0;&lt;br /&gt;
        while (t &amp;lt;= count ){&lt;br /&gt;
&lt;br /&gt;
                printChar(message_str[t]);&lt;br /&gt;
                t += 1;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**************************\n&amp;quot;);&lt;br /&gt;
        printf(&amp;quot;\nClosing...\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        exit(EXIT_SUCCESS);&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Client=== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void chat(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        int fd;&lt;br /&gt;
        char path [] = &amp;quot;watched&amp;quot;;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        const struct timespec timer = {&lt;br /&gt;
                .tv_sec = 0,&lt;br /&gt;
                .tv_nsec = 500000&lt;br /&gt;
        };&lt;br /&gt;
        struct timespec s;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1){&lt;br /&gt;
&lt;br /&gt;
                        buffer[i] = '1';&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        for (a = 0; a &amp;lt; 8; a++) {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                if (buffer[a] == '0'){&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_WRONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                else{&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_RDONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                /*sleep (1);*/&lt;br /&gt;
                nanosleep(&amp;amp;timer,&amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
void main (){&lt;br /&gt;
        char message[1024] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int bit_message;&lt;br /&gt;
        int len = 0;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Type in \n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        fgets(message,100,stdin);&lt;br /&gt;
        printf(&amp;quot;You typed: %s&amp;quot;, message);&lt;br /&gt;
&lt;br /&gt;
        len = (unsigned)strlen(message);&lt;br /&gt;
        while (i &amp;lt; len -1){&lt;br /&gt;
                chat(message[i]);&lt;br /&gt;
                i++;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alessio Trivisonno&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1344</id>
		<title>Esercizi con System Call</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_con_System_Call&amp;diff=1344"/>
		<updated>2016-04-26T14:25:02Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Esperimento: secret channel with inotify&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi contengono esempi di uso delle System-Call.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:03, 2 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
Il gatto di Schr&amp;amp;ouml;dinger: Fork e' vero o falso?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
  if (fork())&lt;br /&gt;
    printf(&amp;quot;fork is true\n&amp;quot;);&lt;br /&gt;
  else&lt;br /&gt;
    printf(&amp;quot;fork is false\n&amp;quot;);&lt;br /&gt;
  usleep(100000);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
il programma stampa entrambi i risultati perché la system call fork() crea un processo figlio identico al padre, questa system call ha come valore di ritorno al thread padre il pid del processo figlio (che essendo diverso da 0 è true) e al thread figlio ritorna 0, quindi il processo padre riceve un valore diverso da 0 (pid del figlio) e stampa true, mentre il processo figlio riceve 0, non entra nel if e stampa, ovviamente false.&lt;br /&gt;
&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
Open() Write() Read()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
/*IL PROGRAMMA APRE UN FILE SUL QUALE FA DELLE OPERAZIONI DI LETTURA E SCRITTURA*/&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_CHAR 100000&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	&lt;br /&gt;
	int fd, c, n_read;&lt;br /&gt;
	int fine = EOF;&lt;br /&gt;
        int index = 0;&lt;br /&gt;
	char arr[MAX_CHAR];&lt;br /&gt;
	char c_arr_read[MAX_CHAR];&lt;br /&gt;
	const char *path = //inserisci qui il percorso del file che vuoi aprire, se il file specificato non esiste, la open fallisce e il &lt;br /&gt;
                           //programma termina con un codice di errore&lt;br /&gt;
	fd = open(path, O_RDWR);&lt;br /&gt;
&lt;br /&gt;
	if(fd == -1){&lt;br /&gt;
		printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
		printf(&amp;quot;Open failed, Err: %d\n&amp;quot;, errno);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	if( (n_read = read(fd, &amp;amp;c_arr_read, MAX_CHAR)) &amp;gt; 0 ) {&lt;br /&gt;
		printf(&amp;quot;file non vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
		write(fd, &amp;amp;fine, 0);&lt;br /&gt;
	} else printf(&amp;quot;file vuoto\nbytes letti: %d\n&amp;quot;, n_read);&lt;br /&gt;
&lt;br /&gt;
	//printf(&amp;quot;fd: %d\n&amp;quot;, fd);&lt;br /&gt;
	printf(&amp;quot;Open().\n&amp;quot;);&lt;br /&gt;
	while((c = getchar()) != EOF &amp;amp;&amp;amp; index &amp;lt; MAX_CHAR){&lt;br /&gt;
		arr[index] = c;&lt;br /&gt;
		index++;&lt;br /&gt;
	}&lt;br /&gt;
	//printf(&amp;quot;sizeof arr: %d\n&amp;quot;, sizeof(arr));&lt;br /&gt;
	write(fd, &amp;amp;arr, index);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
segnali + fork&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pty.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utmp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
&lt;br /&gt;
sigset_t usr12mask;&lt;br /&gt;
sigset_t usr1mask;&lt;br /&gt;
int status;&lt;br /&gt;
int fd, fdout;&lt;br /&gt;
char name[80];&lt;br /&gt;
static int bit;&lt;br /&gt;
char *ar[2] = {&amp;quot;bash&amp;quot;, NULL};&lt;br /&gt;
&lt;br /&gt;
void usr12action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	if (num == SIGCHLD)&lt;br /&gt;
		bit=-1;&lt;br /&gt;
	else {&lt;br /&gt;
		bit = (num == SIGUSR2);&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void usr1action(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char_to_bin(unsigned char x, void *rec){&lt;br /&gt;
	int i;&lt;br /&gt;
	pid_t *r = rec;&lt;br /&gt;
&lt;br /&gt;
	for(i=7; i&amp;gt;=0; i--){&lt;br /&gt;
		char f = x &amp;gt;&amp;gt; i &amp;amp; 1;&lt;br /&gt;
		kill(*r,f?SIGUSR2:SIGUSR1);&lt;br /&gt;
		sigsuspend(&amp;amp;usr1mask);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void *v)&lt;br /&gt;
{&lt;br /&gt;
	sigsuspend(&amp;amp;usr12mask);&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bin2char(int (*f)(void *opaque), void *opaque) {&lt;br /&gt;
	int i;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (i=c=0; i&amp;lt;8; i++) {&lt;br /&gt;
		int n=f(opaque);&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return -1;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			static struct sigaction sa={&lt;br /&gt;
				.sa_sigaction=usr12action,&lt;br /&gt;
				.sa_flags=SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;,getpid());&lt;br /&gt;
&lt;br /&gt;
			sigfillset(&amp;amp;usr12mask);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGINT);&lt;br /&gt;
			sigprocmask(SIG_SETMASK,&amp;amp;usr12mask,NULL);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;usr12mask,SIGUSR2);&lt;br /&gt;
			sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGUSR2,&amp;amp;sa,NULL);&lt;br /&gt;
			sigaction(SIGCHLD,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c=bin2char(readbit,stdin)) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
			if (waitpid(pid, &amp;amp;status, 0) != pid)  status = -1;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			char *path;&lt;br /&gt;
			char *sppid;&lt;br /&gt;
			pid_t ppid=getppid();&lt;br /&gt;
			asprintf(&amp;amp;path,&amp;quot;/proc/%d/exe&amp;quot;,ppid);&lt;br /&gt;
			asprintf(&amp;amp;sppid,&amp;quot;%d&amp;quot;,ppid);&lt;br /&gt;
			execl(&amp;quot;/usr/bin/xterm&amp;quot;, &amp;quot;xterm&amp;quot;, &amp;quot;-e&amp;quot;, path, sppid, (void *) 0);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		unsigned char buf[BUFSIZE];&lt;br /&gt;
		unsigned char *s;&lt;br /&gt;
		pid_t receiver=atoi(argv[1]);&lt;br /&gt;
&lt;br /&gt;
		static struct sigaction sa={.sa_sigaction=usr1action};&lt;br /&gt;
		sigaction(SIGUSR1,&amp;amp;sa,NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		sigfillset(&amp;amp;usr1mask);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGINT);&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;usr1mask,NULL);&lt;br /&gt;
		sigdelset(&amp;amp;usr1mask,SIGUSR1);&lt;br /&gt;
		if (argc == 2){&lt;br /&gt;
			while ((s=fgets(buf,BUFSIZE,stdin))!=NULL){&lt;br /&gt;
				while (*s){&lt;br /&gt;
					char_to_bin(*s++, &amp;amp;receiver);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
il programma in questione &amp;quot;unisce&amp;quot; di fatto i due programmi sigsend e sigrec.&lt;br /&gt;
l'idea è quella che venga lanciato un unico processo e aprire un nuovo terminale dove contiunare l'esecuzione del figlio creato attraverso la fork.&lt;br /&gt;
Possiamo quindi sfruttare il fatto che i due processi (essendo padre e figlio) conoscono i rispettivi pid e quindi automatizzare questa parte senza fornire alcun pid in input.&lt;br /&gt;
è possibile anche fornire un pid come argomento per comunicare con processi diversi.&lt;br /&gt;
([[User:Simone|Simone]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 (Fork del programma 2 di ([[User:Simone|Simone]]) )==&lt;br /&gt;
Sono state effettuate delle piccole modifiche rispetto al programma 2 e inoltre sono stati aggiunti dei commenti per rendere più intuitivo e leggibile il codice.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
sigset_t receiverMask;&lt;br /&gt;
sigset_t senderMask;&lt;br /&gt;
static int bit;&lt;br /&gt;
&lt;br /&gt;
void receiverAction(int num, siginfo_t *info, void *useless) { &lt;br /&gt;
	if (num == SIGCHLD)	// Se il processo figlio del ricevente è terminato&lt;br /&gt;
		bit = EOF;&lt;br /&gt;
	else{&lt;br /&gt;
		bit = (num == SIGUSR2);		// Codifico 1 con il segnale SIGUSR2 e 0 con SIGUSR1&lt;br /&gt;
		kill(info-&amp;gt;si_pid, SIGUSR1);	// Invio il segnale SIGUSR1 al mittente&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void senderAction(int num, siginfo_t *info, void *useless) {&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void write_bin(unsigned char x, pid_t *recv){	/* Funzione che riguarda il mittente */&lt;br /&gt;
	unsigned int i;&lt;br /&gt;
	for(i=0x80; i&amp;gt;0; i&amp;gt;&amp;gt;=1){	// Parto da 10000000, man mano shifto a destra, 01000000, 00100000 ecc ecc, fino a 00000000&lt;br /&gt;
		kill(*recv, (x &amp;amp; i) ? SIGUSR2 : SIGUSR1);	// Invio segnale al ricevente&lt;br /&gt;
		sigsuspend(&amp;amp;senderMask);			// Attendo segnale di ritorno&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int readbit(void){&lt;br /&gt;
	sigsuspend(&amp;amp;receiverMask);     // Sospende il processo e attende un segnale&lt;br /&gt;
	return bit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int read_char(){	/* Funzione che riguarda il ricevente */&lt;br /&gt;
	int i, c;&lt;br /&gt;
	for (i = c = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
		int n = readbit();&lt;br /&gt;
		if (n&amp;lt;0)&lt;br /&gt;
			return EOF;&lt;br /&gt;
		c = c&amp;lt;&amp;lt;1 | n;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(int argc, char *argv[]){&lt;br /&gt;
&lt;br /&gt;
	if (argc == 1) {&lt;br /&gt;
		pid_t pid = fork ();&lt;br /&gt;
&lt;br /&gt;
		if(pid &amp;gt; 0){	/* PROCESSO PADRE (PROCESSO RICEVENTE) */&lt;br /&gt;
			int c;&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Il valore di sa_flag permette di specificare vari aspetti del comportamento di sigaction:&lt;br /&gt;
			 * SA_SIGINFO specifica che si vuole usare un gestore in forma estesa usando sa_sigaction al&lt;br /&gt;
			 * posto di sa_handler. Il valore di sa_sigaction specifica la funzione da chiamare, permettendo&lt;br /&gt;
			 * di usare un gestore piu complesso, in grado di ricevere informazioni piu dettagliate dal&lt;br /&gt;
			 * sistema, attraverso la struttura siginfo_t&lt;br /&gt;
			 */&lt;br /&gt;
			struct sigaction sa = {&lt;br /&gt;
				.sa_sigaction = receiverAction,&lt;br /&gt;
				.sa_flags = SA_SIGINFO&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			printf(&amp;quot;%d\n&amp;quot;, getpid());&lt;br /&gt;
&lt;br /&gt;
			/* Inserisci tutti i segnali nell'insieme receiverMask */&lt;br /&gt;
			sigfillset(&amp;amp;receiverMask);&lt;br /&gt;
&lt;br /&gt;
			/* Elimina il segnale SIGINT dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGINT);&lt;br /&gt;
&lt;br /&gt;
			/* Setta la maschera dei segnali del processo con l'insieme receiverMask.&lt;br /&gt;
			 * Il valore NULL indica che la maschera attuale del processo non verrà salvata. */&lt;br /&gt;
			sigprocmask(SIG_SETMASK, &amp;amp;receiverMask, NULL);&lt;br /&gt;
			&lt;br /&gt;
			/* Elimina il segnale SIGCHLD, SIGUSR1 e SIGUSR2 dall'insieme receiverMask */&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGCHLD);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR1);&lt;br /&gt;
			sigdelset(&amp;amp;receiverMask, SIGUSR2);&lt;br /&gt;
			&lt;br /&gt;
			/* Setta l'azione sa per i segnali SIGUSR1, SIGUSR2 e SIGCHLD. &lt;br /&gt;
			 * Il valore NULL indica che l’azione corrente non viene restituita indietro. */&lt;br /&gt;
			sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGUSR2, &amp;amp;sa, NULL);&lt;br /&gt;
			sigaction(SIGCHLD, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
			while ((c = read_char()) != EOF)&lt;br /&gt;
				putchar(c);&lt;br /&gt;
		&lt;br /&gt;
		}&lt;br /&gt;
		else if(pid == 0){	// PROCESSO FIGLIO&lt;br /&gt;
			char *cmd;&lt;br /&gt;
			pid_t ppid = getppid();	/* PID del processo padre (ricevente) */&lt;br /&gt;
&lt;br /&gt;
                        /* Avvio un altro terminale eseguendo lo stesso programma con parametri di input */&lt;br /&gt;
			asprintf(&amp;amp;cmd, &amp;quot;xterm -e /proc/%d/exe %d&amp;quot;, ppid, ppid);	&lt;br /&gt;
			system(cmd);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
		else{	// Errore Fork&lt;br /&gt;
			fprintf(stderr, &amp;quot;Errore fork&amp;quot;);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
	} else {	/* PROCESSO MITTENTE */&lt;br /&gt;
		unsigned char buf[BUFSIZE], *read;&lt;br /&gt;
		pid_t receiver = atoi(argv[1]);	   // Pid del ricevente&lt;br /&gt;
		&lt;br /&gt;
		/* Setto una banale azione (usr1action) alla ricezione del segnale SIGUSR1*/&lt;br /&gt;
		struct sigaction sa = {.sa_sigaction = senderAction}; &lt;br /&gt;
		sigaction(SIGUSR1, &amp;amp;sa, NULL);&lt;br /&gt;
&lt;br /&gt;
		printf(&amp;quot;%d-&amp;gt;%d\n&amp;quot;,getpid(),receiver);&lt;br /&gt;
		&lt;br /&gt;
		sigfillset(&amp;amp;senderMask);		        // Inserisco tutti i segnali nell'insieme senderMask&lt;br /&gt;
		sigdelset(&amp;amp;senderMask, SIGINT); 		// e cancello dall'insieme il segnale SIGINT.&lt;br /&gt;
		sigprocmask(SIG_SETMASK,&amp;amp;senderMask,NULL);	// Setto la maschera creata per il processo corrente, senza salvare la precedente.&lt;br /&gt;
		sigdelset(&amp;amp;senderMask,SIGUSR1);			// Elimino il segnale SIGUSR1 dall'insieme.&lt;br /&gt;
		if (argc == 2){					// Se i paramentri in input sono 2&lt;br /&gt;
			while ((read = fgets(buf,BUFSIZE,stdin)) != NULL){     // Leggo dallo stdin&lt;br /&gt;
				while (*read)				       // Leggo tutta la stringa&lt;br /&gt;
					write_bin(*read++, &amp;amp;receiver);	       // Invio ogni singolo carattere della stringa al ricevente&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= programma 5 =&lt;br /&gt;
==Secret channel with inotify==&lt;br /&gt;
Stavo leggendo sul libro che e' possibile creare un canale di comunicazione segreto praticamente con ogni cosa all'interno di un sistema UNIX. In particolare mi ha interessato il caso di creare un canale mono direzionale tramite l'apertura dei file in lettura o scrittura e ho voluto provare a implementarne uno. Questi canali sono quasi impossibili da scovare per un amministratore di sistema e potrebbero permettere lo scambio di informazioni illecite. &lt;br /&gt;
Una cosa interessante e' che a quanto pare il kernel ha bisogno di qualche millisecondo per eseguire la inotify e che una precedente implementazione senza delay portava all'arrivo di messaggi sbagliati.&lt;br /&gt;
&lt;br /&gt;
===Server===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void printChar(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        char c;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1)&lt;br /&gt;
                        buffer[i]= '1';&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        c = strtol(buffer, 0, 2);&lt;br /&gt;
        printf(&amp;quot;%c&amp;quot;, c);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void handle_events (int fd, int wd, char *bin_message,int *current_bit){&lt;br /&gt;
        char buf [4096]&lt;br /&gt;
        __attribute__ ((aligned(__alignof__(struct inotify_event))));&lt;br /&gt;
        const struct inotify_event *event;&lt;br /&gt;
        int i;&lt;br /&gt;
        ssize_t len;&lt;br /&gt;
        char *ptr;&lt;br /&gt;
&lt;br /&gt;
        //loop while inotify events can be read from the fd&lt;br /&gt;
        for (;;){&lt;br /&gt;
                len = read (fd, buf, sizeof (buf));&lt;br /&gt;
                if (len == -1 &amp;amp;&amp;amp; errno != EAGAIN){&lt;br /&gt;
                        perror (&amp;quot;read&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                //if the read returns with the errono EAGAIN exit from the loop&lt;br /&gt;
                if (len &amp;lt;= 0)&lt;br /&gt;
                        break;&lt;br /&gt;
                //loop between all events in the buffer&lt;br /&gt;
                for (ptr = buf; ptr &amp;lt; buf + len;&lt;br /&gt;
                                ptr += sizeof(struct inotify_event) + event-&amp;gt;len){&lt;br /&gt;
                        event = (const struct inotify_event *) ptr;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_NOWRITE){&lt;br /&gt;
                                //received 1&lt;br /&gt;
&lt;br /&gt;
                                *bin_message |= 0x01;&lt;br /&gt;
                        }&lt;br /&gt;
                        if (event-&amp;gt;mask &amp;amp; IN_CLOSE_WRITE){&lt;br /&gt;
&lt;br /&gt;
                                //received 0&lt;br /&gt;
                                //do nothing to leave 0&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        &lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void main () {&lt;br /&gt;
        char buf;&lt;br /&gt;
        int fd;&lt;br /&gt;
        int wd;&lt;br /&gt;
        struct pollfd fds [2];&lt;br /&gt;
        int nfds;&lt;br /&gt;
        int poll_num;&lt;br /&gt;
        /*char message = 0;*/&lt;br /&gt;
        unsigned char message_str [4096] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int count = 0;&lt;br /&gt;
        int bit_wrote = 0;&lt;br /&gt;
         &lt;br /&gt;
        char path [100] = &amp;quot;/inofify/watched&amp;quot;;&lt;br /&gt;
        int t;&lt;br /&gt;
&lt;br /&gt;
        //create the file descriptor where inotify events has to be read&lt;br /&gt;
        fd = inotify_init1(IN_NONBLOCK);&lt;br /&gt;
        if (fd == -1) {&lt;br /&gt;
                perror(&amp;quot;inotify_init1&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        wd = inotify_add_watch (fd, path, IN_CLOSE_NOWRITE | IN_CLOSE_WRITE);&lt;br /&gt;
&lt;br /&gt;
        if (wd == -1 ){&lt;br /&gt;
                fprintf (stderr, &amp;quot;Cannot watch '%s' \n&amp;quot;, path);&lt;br /&gt;
                perror (&amp;quot;inotify_add_watch&amp;quot;);&lt;br /&gt;
                exit(EXIT_FAILURE);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //prepare for the polling on the fd&lt;br /&gt;
&lt;br /&gt;
        nfds = 2;&lt;br /&gt;
        fds[0].fd = STDIN_FILENO;&lt;br /&gt;
        fds[0].events = POLLIN;&lt;br /&gt;
        fds[1].fd = fd;&lt;br /&gt;
        fds[1].events = POLLIN;&lt;br /&gt;
&lt;br /&gt;
        printf (&amp;quot;Listening for events... Press ENTER to terminate and show the message\n&amp;quot;);&lt;br /&gt;
        while (1){&lt;br /&gt;
&lt;br /&gt;
                poll_num = poll(fds,nfds, -1);&lt;br /&gt;
                if (poll_num == -1){&lt;br /&gt;
                        if (errno == EINTR)&lt;br /&gt;
                                continue;&lt;br /&gt;
                        perror (&amp;quot;poll&amp;quot;);&lt;br /&gt;
                        exit (EXIT_FAILURE);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                if (poll_num &amp;gt; 0){&lt;br /&gt;
                        if (fds[0].revents &amp;amp; POLLIN){&lt;br /&gt;
&lt;br /&gt;
                                //exit on ENTER key pressed emptying the stdin&lt;br /&gt;
                                while (read (STDIN_FILENO,&amp;amp;buf,1) &amp;gt; 0 &amp;amp;&amp;amp; buf != '\n') continue;&lt;br /&gt;
                                break;&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                        }&lt;br /&gt;
                        //notify an event occurred&lt;br /&gt;
                        if (fds[1].revents &amp;amp; POLLIN ){&lt;br /&gt;
                                if (bit_wrote &amp;lt; 8){&lt;br /&gt;
                                        printf(&amp;quot;..&amp;quot;);&lt;br /&gt;
                                        fflush(stdout);&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                        if (bit_wrote &amp;lt; 7){&lt;br /&gt;
                                                message_str[count] = message_str[count] &amp;lt;&amp;lt; 0x01;&lt;br /&gt;
                                        }&lt;br /&gt;
&lt;br /&gt;
                                }&lt;br /&gt;
                                else {&lt;br /&gt;
                                        bit_wrote = 0;&lt;br /&gt;
                                        count += 1;&lt;br /&gt;
                                        handle_events (fd,wd,&amp;amp;message_str[count],&amp;amp;bit_wrote);&lt;br /&gt;
                                }&lt;br /&gt;
                                bit_wrote += 1;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**********MESSAGE***********\n&amp;quot;);&lt;br /&gt;
        t = 0;&lt;br /&gt;
        while (t &amp;lt;= count ){&lt;br /&gt;
&lt;br /&gt;
                printChar(message_str[t]);&lt;br /&gt;
                t += 1;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n**************************\n&amp;quot;);&lt;br /&gt;
        printf(&amp;quot;\nClosing...\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        exit(EXIT_SUCCESS);&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Client=== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void chat(int n){&lt;br /&gt;
&lt;br /&gt;
        int a;&lt;br /&gt;
        int fd;&lt;br /&gt;
        char path [] = &amp;quot;watched&amp;quot;;&lt;br /&gt;
        unsigned char buffer[8];&lt;br /&gt;
        memset(buffer, '0', sizeof(buffer));&lt;br /&gt;
        int i = 7;&lt;br /&gt;
        const struct timespec timer = {&lt;br /&gt;
                .tv_sec = 0,&lt;br /&gt;
                .tv_nsec = 500000&lt;br /&gt;
        };&lt;br /&gt;
        struct timespec s;&lt;br /&gt;
        while (n){&lt;br /&gt;
&lt;br /&gt;
                if(n &amp;amp; 1){&lt;br /&gt;
&lt;br /&gt;
                        buffer[i] = '1';&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                i--;&lt;br /&gt;
                n &amp;gt;&amp;gt;= 1;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        for (a = 0; a &amp;lt; 8; a++) {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                /*printf (&amp;quot;%c&amp;quot;,buffer[a]);*/&lt;br /&gt;
                if (buffer[a] == '0'){&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_WRONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
&lt;br /&gt;
                }&lt;br /&gt;
                else{&lt;br /&gt;
&lt;br /&gt;
                        fd = open(path,O_RDONLY);&lt;br /&gt;
                        close(fd);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                /*sleep (1);*/&lt;br /&gt;
                nanosleep(&amp;amp;timer,&amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
void main (){&lt;br /&gt;
        char message[1024] = &amp;quot;&amp;quot;;&lt;br /&gt;
        int bit_message;&lt;br /&gt;
        int len = 0;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Type in \n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        fgets(message,100,stdin);&lt;br /&gt;
        printf(&amp;quot;You typed: %s&amp;quot;, message);&lt;br /&gt;
&lt;br /&gt;
        len = (unsigned)strlen(message);&lt;br /&gt;
        while (i &amp;lt; len -1){&lt;br /&gt;
                chat(message[i]);&lt;br /&gt;
                i++;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alessio Trivisonno&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_lettura_di_codice_C&amp;diff=1257</id>
		<title>Esercizi di lettura di codice C</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_lettura_di_codice_C&amp;diff=1257"/>
		<updated>2015-11-07T20:37:53Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Soluzione programma 9&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi non sono necessariamente stilisticamente belli (non sono &amp;quot;esempi da copiare&amp;quot;) ma presentano dei passaggi di non semplice lettura.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 15:42, 10 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int c;&lt;br /&gt;
        while ((c=getchar())!=EOF)&lt;br /&gt;
                putchar(c);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio tutto ciò che viene preso in input viene messo in output, fino a quando non viene digitato il carattere di End of File (EOF). Solitamente nei sistemi DOS il carattere EOF viene definito come la combinazione di tasti CTRL+Z, mentre nei sistemi basati su Unix si utilizzano i tasti CTRL+D. ([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
Nel caso l'input provenga da file e non da tastiera (ad esempio eseguendo da terminale la riga di comando &amp;quot;./programma0 &amp;lt; testo&amp;quot;), il carattere speciale EOF viene inserito automaticamente alla fine del file &amp;quot;testo&amp;quot;. In questo caso il programma prende in input il contenuto di &amp;quot;testo&amp;quot; e stampa a video (carattere per carattere), il contenuto del file, finchè non riconosce il carattere speciale EOF, che fa terminare il ciclo while.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
questo &amp;amp;egrave; l'esercizio visto in aula. Il punto da notare &amp;amp;egrave; l'uso dell'assegnazione all'interno del controllo del ciclo while. E' una struttura tipica del linguaggio C che semplifica sintatticamente la scrittura del programma.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:02, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
char s1[]=&amp;quot;hello world&amp;quot;;&lt;br /&gt;
char *s2=&amp;quot;hello world&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
void foo(char *s) {&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,s);&lt;br /&gt;
        s[4]=',';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,s);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        foo(s1);&lt;br /&gt;
        foo(s2);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio viene mostrata la differenza tra stringa variabile (s1) e stringa costante (s2). Nel primo caso a tempo di compilazione la stringa costante &amp;quot;hello world&amp;quot; viene copiata passo nella stringa variabile s1 consentendo le normali operazioni di modifica della stringa stessa. Mentre nel secondo caso a tempo di compilazione viene creata la stringa costante &amp;quot;hello world&amp;quot; e memorizzato il suo indirizzo nella variabile s2 NON consentendo le normali operazioni di modifica delle stringa stessa in quanto appunto un costante. ([[User:S.G|S.G]])&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
char t[]=&amp;quot;test&amp;quot;;&lt;br /&gt;
struct st {&lt;br /&gt;
        char s[5];&lt;br /&gt;
        char *t;&lt;br /&gt;
} st0={&amp;quot;test&amp;quot;,t};&lt;br /&gt;
&lt;br /&gt;
void foo (struct st i) {&lt;br /&gt;
        i.s[2]='n';&lt;br /&gt;
        i.t[2]='n';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bar (struct st *i) {&lt;br /&gt;
        i-&amp;gt;s[2]='x';&lt;br /&gt;
        i-&amp;gt;t[2]='x';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t);&lt;br /&gt;
        foo(st0); /* Vengono copiati i valori della struttura st0 in i, le uniche modifiche saranno sul campo i.t in quanto puntatore. */&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t); &lt;br /&gt;
        bar(&amp;amp;st0); /* Viene copiato l'indirizzo della struttura st0 in i, le modifiche vengono apportate su tutti i campi delle struttura. */&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Output del programma:&lt;br /&gt;
&lt;br /&gt;
test test&lt;br /&gt;
&lt;br /&gt;
test tent&lt;br /&gt;
&lt;br /&gt;
text text&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
S&amp;amp;igrave;, ma perch&amp;amp;eacute;? Come &amp;amp;egrave; fatta la struttura st? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:06, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
La struttura st è fatta da un array di 5 caratteri e da un puntatore a caratteri (che viene usato anch'esso per puntare ad un'array di caratteri).&lt;br /&gt;
&lt;br /&gt;
Con la prima chiamata a printf vengono stampati i valori dei campi della struttura non ancora modificati, dal momento che non è stata ancora chiamata nè la funzione foo nè la funzione bar (test test)&lt;br /&gt;
&lt;br /&gt;
In seguito viene passata la struct st0 alla funzione foo. In particolare viene passata alla funzione una COPIA del primo campo e una COPIA del secondo campo; tuttavia essendo il secondo campo della struttura un puntatore, viene passato il valore del puntatore, che è un indirizzo, cioè l'indirizzo a cui si trova l'array t (char t[]=&amp;quot;test&amp;quot;). Per questo motivo viene modificato solo il valore del secondo campo nella struttura st0, infatti quando la funzione termina, la copia del primo campo viene persa, senza aver modificato il valore originale, mentre il valore del secondo campo viene modificato perchè l'abbiamo modificato tramite l'indirizzo. L'output finale sarà quindi: test tent.&lt;br /&gt;
&lt;br /&gt;
Alla chiamata alla funzione bar, viene invece passato l'INDIRIZZO della struttura st0, e per questo quando andiamo a modificare i campi della struttura all'interno della funzione bar, non stiamo modificando una copia di st0, ma stiamo modificando direttamente st0, accedendo tramite puntatore ai suoi singoli campi. Quindi quando bar termina, i valori originali sono stati modificati e l'output risulterà: text text.&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        while (argc &amp;gt; 1) {&lt;br /&gt;
                int i,j;&lt;br /&gt;
                char *s=argv[1];&lt;br /&gt;
                for (i=0, j=strlen(s)-1; i &amp;lt; j; i++, j--)&lt;br /&gt;
                        s[i] ^= s[j], s[j] ^= s[i], s[i] ^= s[j];&lt;br /&gt;
                printf(&amp;quot;%s &amp;quot;,s);&lt;br /&gt;
                argc--;&lt;br /&gt;
                argv++;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio il programma effettua un reverse di tutte le parole che gli vengo date in input ad esclusione di argv[0] che sarebbe il nome del programma, esempio:&lt;br /&gt;
&lt;br /&gt;
INPUT: ./programma3 ciao sistemi operativi&lt;br /&gt;
&lt;br /&gt;
OUTPUT: oaic imetsis ivitarepo&lt;br /&gt;
&lt;br /&gt;
Il punto importante di questo codice è che lo scambio delle singole lettere viene effettuato con l'operatore logico XOR senza cosi avere bisogno di una &amp;quot;variabile di scambio&amp;quot;.&lt;br /&gt;
Qui viene spiegato nel dettaglio il [https://it.wikibooks.org/wiki/C/Variabili,_operatori_e_costanti/Operatori_sui_bit funzionamento dell'operatore logico]&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
== programma 4 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct elem {&lt;br /&gt;
        char *s;&lt;br /&gt;
        struct elem *next;&lt;br /&gt;
};&lt;br /&gt;
struct elem *root=NULL;&lt;br /&gt;
&lt;br /&gt;
void insert(char *s, struct elem **elp) { /* Inserimento in ordine alfabetico */&lt;br /&gt;
        if (*elp &amp;amp;&amp;amp; strcmp((*elp)-&amp;gt;s, s) &amp;lt; 0) /* se la lista elp non è vuota e se (*elp)-&amp;gt;s è alfabeticamente minore di s, inserisce in coda s */&lt;br /&gt;
                insert(s,&amp;amp;((*elp)-&amp;gt;next));&lt;br /&gt;
        else { /* nel caso in cui la lista è vuota o se (*elp)-&amp;gt;s è alfabeticamente maggiore di s, inserisce in testa s */&lt;br /&gt;
                struct elem tmp={s,*elp};&lt;br /&gt;
                struct elem *new=malloc(sizeof(struct elem));&lt;br /&gt;
                *new=tmp;&lt;br /&gt;
                *elp=new;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct elem *print(struct elem *root) { /* stampa l'intera lista, alla fine dealloca root e restituisce NULL */&lt;br /&gt;
        if (root) {&lt;br /&gt;
                printf(&amp;quot;%s &amp;quot;,root-&amp;gt;s);&lt;br /&gt;
                root-&amp;gt;next=print(root-&amp;gt;next);&lt;br /&gt;
                free(root);&lt;br /&gt;
                return NULL;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        for (;argc&amp;gt;1;argc--,argv++) /* Scorre tutti gli elementi in input del programma (tranne il nome stesso del programma), aggiungendoli in una lista */&lt;br /&gt;
                insert(argv[1],&amp;amp;root);&lt;br /&gt;
        root=print(root);&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il programma ordina alfabeticamente gli elementi presi input, esempio: &lt;br /&gt;
&lt;br /&gt;
INPUT: ./programma4 ciao sistemi operativi e macchine virtuali&lt;br /&gt;
&lt;br /&gt;
OUTPUT: ciao e macchine operativi sistemi virtuali&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Per&amp;amp;ograve; ci sono due tecniche diverse per la scrittura di funzioni ricorsive che modificano liste... Chi le spiega? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:08, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
In quanto la lista va modificata, in questo esempio, è stato passato l'indirizzo di memoria del puntatore di testa della lista. Ne verrà quindi usata una copia all'interno della funzione ma, essendo una copia di un indirizzo di memoria, si andrà ugualmente ad agire fisicamente sulla struttura dati.&lt;br /&gt;
La seconda opzione è quella di passare la testa della lista come parametro, così facendo però ne verrà creata una copia. Per rendere quindi effettive le modifiche che avvengono nella funzione, bisogna quindi che la funzione non abbia risultato Void bensì deve ritornare come valore la testa della lista modificata. Nella chiamata della funzione è quindi necessario un assegnamento del tipo: head = func(head);&lt;br /&gt;
&lt;br /&gt;
Alessandro Bandini&lt;br /&gt;
&lt;br /&gt;
==Programma 5==&lt;br /&gt;
Propongo un esempio relativo all'uso dello statement static:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int var;&lt;br /&gt;
&lt;br /&gt;
int foo(){&lt;br /&gt;
	static int var=0;&lt;br /&gt;
	var++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bar(){&lt;br /&gt;
	int var=0;&lt;br /&gt;
	var ++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int foobar(){&lt;br /&gt;
	var++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	int sum1, sum2, sum3;&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum1=foo();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum1);&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum2=bar();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum2);&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum3=foobar();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum3);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output del codice:&lt;br /&gt;
&lt;br /&gt;
100&lt;br /&gt;
&lt;br /&gt;
1&lt;br /&gt;
&lt;br /&gt;
100&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Le tre funzioni ''foo()'', ''bar()'' e ''foobar()'', sebbene si possa pensare agiscano sulla stessa variabile globale intera ''var'', hanno comportamenti diversi proprio perche' non agiscono sulla stessa variabile. Nella funzione ''foo()'', viene ridefinita una nuova variabile intera ''var'' che ha uno scope limitato al solo corpo della funzione (e' come se avesse una &amp;quot;precedenza&amp;quot; maggiore rispetto alla variabile globale); inoltre essa e' definita come ''static'': il valore della varibile non viene quindi salvato nello STACK della funzione bensi' nel segmento DATA, permettendo di avere il valore salvato anche dopo piu' chiamate della funzione.&lt;br /&gt;
&lt;br /&gt;
Il discorso e' leggermente diverso per la funzione ''bar()'': anche qui viene ridefinita la variabile ''var'' ma non in modo static. Il valore di ''var'' e' quindi salvato nello STACK della funzione, che viene ricreato ad ogni chiamata. Sebbene ''bar()'' venga chiamata cento volte, a ''sum2'' viene assegnato solo un incremento, a causa dell'inizializzazione a 0 di ''var'' che avviene per ogni chiamata.&lt;br /&gt;
&lt;br /&gt;
Infine, all'interno della funzione ''foobar()'' non viene definita una nuova variabile, quindi la ''var'' usata nel corpo e' la variabile globale definita in precedenza. Similmente ad una variabile static, anche il valore di una variabile globale viene memorizzato nel segmento DATA del programma, ed il cui valore rimane in memoria nonostante le successive chiamate della funzione.&lt;br /&gt;
&lt;br /&gt;
Matteo Del Vecchio&lt;br /&gt;
&lt;br /&gt;
==Programma 6==&lt;br /&gt;
Challenge: Cosa fa questo programma (progettato per processori atmega8/88/168 etc)?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#ifdef ATMEGA88&lt;br /&gt;
#define F_CPU 8000000UL  // 8 MHz&lt;br /&gt;
#else&lt;br /&gt;
#define F_CPU 1000000UL  // 1 MHz&lt;br /&gt;
#endif&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void delay_ms(unsigned int ms)&lt;br /&gt;
{&lt;br /&gt;
        while(ms){&lt;br /&gt;
                _delay_ms(0.96);&lt;br /&gt;
                ms--;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#define DMASK 0x07&lt;br /&gt;
#define TWSR_STATUS_MASK 0xF8&lt;br /&gt;
#define TWCR_CMD_MASK 0x0F&lt;br /&gt;
&lt;br /&gt;
unsigned char newB;&lt;br /&gt;
unsigned char oldB;&lt;br /&gt;
unsigned char diffB;&lt;br /&gt;
unsigned char status;&lt;br /&gt;
unsigned char unstable;&lt;br /&gt;
unsigned char step;&lt;br /&gt;
unsigned char value;&lt;br /&gt;
unsigned char d0,d1,d2,d3,d4,d5,d6,d7,d8;&lt;br /&gt;
&lt;br /&gt;
static unsigned char i2cs_addr;&lt;br /&gt;
&lt;br /&gt;
void i2cs_init(void)&lt;br /&gt;
{&lt;br /&gt;
        TWCR = 1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA | 1&amp;lt;&amp;lt;TWEN | 1&amp;lt;&amp;lt;TWIE;&lt;br /&gt;
        TWAR = i2cs_addr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void i2cs_command(unsigned char comm)&lt;br /&gt;
{&lt;br /&gt;
        switch (comm &amp;amp; 0xF8) {&lt;br /&gt;
                case 0x80:&lt;br /&gt;
                        if (step)&lt;br /&gt;
                                status &amp;amp;= ~(1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        else&lt;br /&gt;
                                PORTD &amp;amp;= ~(1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        break;&lt;br /&gt;
                case 0x88:&lt;br /&gt;
                        if (step)&lt;br /&gt;
                                status |= (1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        else&lt;br /&gt;
                                PORTD |= (1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        break;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TWI_vect)&lt;br /&gt;
{&lt;br /&gt;
        unsigned char i2c_status= TWSR &amp;amp; TWSR_STATUS_MASK;&lt;br /&gt;
        switch (i2c_status) {&lt;br /&gt;
                case TW_SR_DATA_ACK:&lt;br /&gt;
                        i2cs_command(TWDR);&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
                case TW_ST_SLA_ACK:&lt;br /&gt;
                case TW_ST_DATA_ACK:&lt;br /&gt;
                        TWDR = status;&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
                default:&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
        DDRD = 0xFF;&lt;br /&gt;
        PORTB = 0xFF;&lt;br /&gt;
        PORTC = 0x0F;&lt;br /&gt;
        delay_ms(10);&lt;br /&gt;
        i2cs_addr= (0x20 | ((~PINC &amp;amp; 0x0F) &amp;lt;&amp;lt; 1));&lt;br /&gt;
        step = (i2cs_addr &amp;amp; 0x10) == 0;&lt;br /&gt;
        i2cs_init();&lt;br /&gt;
        sei();&lt;br /&gt;
        while (1) {&lt;br /&gt;
                delay_ms(1);&lt;br /&gt;
                oldB=newB;&lt;br /&gt;
                newB=~PINB;&lt;br /&gt;
                diffB=oldB ^ newB;&lt;br /&gt;
                unstable=0;&lt;br /&gt;
                if (diffB &amp;amp; 0x01) d0 = 1; else d0++; &lt;br /&gt;
                if (diffB &amp;amp; 0x02) d1 = 1; else d1++;&lt;br /&gt;
                if (diffB &amp;amp; 0x04) d2 = 1; else d2++;&lt;br /&gt;
                if (diffB &amp;amp; 0x08) d3 = 1; else d3++;&lt;br /&gt;
                if (diffB &amp;amp; 0x10) d4 = 1; else d4++;&lt;br /&gt;
                if (diffB &amp;amp; 0x20) d5 = 1; else d5++;&lt;br /&gt;
                if (diffB &amp;amp; 0x40) d6 = 1; else d6++;&lt;br /&gt;
                if (diffB &amp;amp; 0x80) d7 = 1; else d7++;&lt;br /&gt;
                if(d0 &amp;amp; DMASK) unstable |= 0x01;&lt;br /&gt;
                if(d1 &amp;amp; DMASK) unstable |= 0x02;&lt;br /&gt;
                if(d2 &amp;amp; DMASK) unstable |= 0x04;&lt;br /&gt;
                if(d3 &amp;amp; DMASK) unstable |= 0x08;&lt;br /&gt;
                if(d4 &amp;amp; DMASK) unstable |= 0x10;&lt;br /&gt;
                if(d5 &amp;amp; DMASK) unstable |= 0x20;&lt;br /&gt;
                if(d6 &amp;amp; DMASK) unstable |= 0x40;&lt;br /&gt;
                if(d7 &amp;amp; DMASK) unstable |= 0x80;&lt;br /&gt;
                if (step) {&lt;br /&gt;
                        status ^= (newB &amp;amp; ~value &amp;amp; ~unstable);&lt;br /&gt;
                        value = (value &amp;amp; unstable) | (newB &amp;amp; ~unstable);&lt;br /&gt;
                } else&lt;br /&gt;
                        status = (status &amp;amp; unstable) | (newB &amp;amp; ~unstable);&lt;br /&gt;
                if (step)&lt;br /&gt;
                        PORTD=status;&lt;br /&gt;
        }&lt;br /&gt;
        return(0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:06, 21 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
==Programma 7==&lt;br /&gt;
Guardate queste costanti predefinite. Come le utilizzereste?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  printf(&amp;quot;%s: line %d\n&amp;quot;,__FILE__,__LINE__);&lt;br /&gt;
  printf(&amp;quot;built %s %s\n&amp;quot;,__DATE__,__TIME__);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 8==&lt;br /&gt;
Un &amp;quot;effetto speciale&amp;quot; del preprocessore:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#define ik(x) int k##x = x&lt;br /&gt;
#define ck(x) char *k##x = #x&lt;br /&gt;
&lt;br /&gt;
ik(0);&lt;br /&gt;
ik(1);&lt;br /&gt;
ik(2);&lt;br /&gt;
ck(tricky);&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  printf(&amp;quot;%d %d %d %s\n&amp;quot;, k0, k1, k2, ktricky);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il programma stampa: 0 1 2 tricky&lt;br /&gt;
&lt;br /&gt;
Questo e' dovuto al fatto che il preprocessore sostituisce ogni occorrenza di ik(x) con int kx = x; Lo stesso avviene per la stringa tricky. Infatti se andiamo a guardare il programma facendo solo la fase di preproccessing dando il comando gcc -E [...] notiamo che diventa cosi':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int k0 = 0;&lt;br /&gt;
int k1 = 1;&lt;br /&gt;
int k2 = 2;&lt;br /&gt;
char *ktricky = &amp;quot;tricky&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
      printf(&amp;quot;%d %d %d %s\n&amp;quot;, k0, k1, k2, ktricky);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'operatore ## concatena due argomenti senza lasciare spazi bianchi tra di loro, in questo caso concatena k ad x.&lt;br /&gt;
&amp;lt;br/&amp;gt;Non importa che ci sia uno spazio tra k e x. Vedi [http://www.cplusplus.com/doc/oldtutorial/preprocessor/]&lt;br /&gt;
&lt;br /&gt;
[[User:Aletri|Aletri]] ([[User talk:Aletri|talk]])&lt;br /&gt;
&lt;br /&gt;
==Programma 9==&lt;br /&gt;
Ecco un esempio di uso della libreria stdarg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void intprint(int n, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list ap;&lt;br /&gt;
&lt;br /&gt;
  va_start(ap, n);&lt;br /&gt;
  while (n&amp;gt;0) {&lt;br /&gt;
    int i;&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;,va_arg(ap,int));&lt;br /&gt;
    n--;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  va_end(ap);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv) {&lt;br /&gt;
  intprint(3,1,2,3);&lt;br /&gt;
  intprint(5,1,2,3,4,5);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'uso della libreria stdarg e' particolarmente utile quando la funzione chiamata non conosce il numero di argomenti che le verranno passati. Infatti possiamo notare che intprint viene chiamata la prima volta con 4 parametri e la seconda volta con 6. Questo viene grestito dalla libreria mettendo gli argomenti nella lista va_list. Questa libreria utilizza delle macro per getire questa operazione. In particolare potete notare facendo solo il preprocessing che va_start e va_end vengono sostituiti con delle macro.&lt;br /&gt;
&lt;br /&gt;
Il programma stampa 123 12345.&lt;br /&gt;
&lt;br /&gt;
[[User:Aletri|Aletri]] ([[User talk:Aletri|talk]])&lt;br /&gt;
&lt;br /&gt;
==Programma 10==&lt;br /&gt;
Un po' di trucchi con le macro e le funzioni a numero variabile di parametri con passaggio di liste di parametri.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define debugprintf(fmt, ...) private_debugprintf((fmt),__FILE__,__LINE__, ##__VA_ARGS__)&lt;br /&gt;
&lt;br /&gt;
int private_debugprintf(const char *fmt, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list ap;&lt;br /&gt;
  char *newfmt;&lt;br /&gt;
  int rv;&lt;br /&gt;
&lt;br /&gt;
  va_start(ap, fmt);&lt;br /&gt;
  asprintf(&amp;amp;newfmt,&amp;quot;File %%s Line %%d %s&amp;quot;,fmt);&lt;br /&gt;
  rv=vfprintf(stderr, newfmt, ap);&lt;br /&gt;
  free(newfmt);&lt;br /&gt;
  return rv;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char *name=&amp;quot;douglas adams&amp;quot;;&lt;br /&gt;
int value=42;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  debugprintf(&amp;quot;hello world, bug!\n&amp;quot;);&lt;br /&gt;
  debugprintf(&amp;quot;string: %s int: %d\n&amp;quot;,name,value);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 11==&lt;br /&gt;
getopt e getopt_long sono molto utili.... ecco un esempio. Cosa fa questo programma?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;getopt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libgen.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void usage(char *progname) {&lt;br /&gt;
  fprintf(stderr,&lt;br /&gt;
      &amp;quot;Usage:\n&amp;quot;&lt;br /&gt;
      &amp;quot;\t%s [-m num] [-r] args...\n&amp;quot;&lt;br /&gt;
      &amp;quot;\t%s [--mul num] [--rev] args...\n&amp;quot;,progname,progname);&lt;br /&gt;
  exit(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  int c, oindex;&lt;br /&gt;
  int rev=0;&lt;br /&gt;
  int mul=1;&lt;br /&gt;
  static struct option long_options[] = {&lt;br /&gt;
    {&amp;quot;mul&amp;quot;, required_argument, 0, 'm'},&lt;br /&gt;
    {&amp;quot;rev&amp;quot;, no_argument, 0, 'r'}};&lt;br /&gt;
  while ((c = getopt_long(argc, argv, &amp;quot;m:r&amp;quot;,&lt;br /&gt;
          long_options, &amp;amp;oindex)) &amp;gt; 0) {&lt;br /&gt;
    switch (c) {&lt;br /&gt;
      case 'm': mul = atoi(optarg);&lt;br /&gt;
                break;&lt;br /&gt;
      case 'r': rev = 1;&lt;br /&gt;
                break;&lt;br /&gt;
      default:&lt;br /&gt;
                usage(basename(argv[0]));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  for (; mul&amp;gt;0; mul--) {&lt;br /&gt;
    if (rev) {&lt;br /&gt;
      for(oindex=argc-1; oindex&amp;gt;=optind; oindex--)&lt;br /&gt;
        printf(&amp;quot;%s &amp;quot;,argv[oindex]);&lt;br /&gt;
    } else {&lt;br /&gt;
      for(oindex=optind; oindex&amp;lt;argc; oindex++)&lt;br /&gt;
        printf(&amp;quot;%s &amp;quot;,argv[oindex]);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_lettura_di_codice_C&amp;diff=1256</id>
		<title>Esercizi di lettura di codice C</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_lettura_di_codice_C&amp;diff=1256"/>
		<updated>2015-11-07T20:19:51Z</updated>

		<summary type="html">&lt;p&gt;Aletri: /* Programma 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi non sono necessariamente stilisticamente belli (non sono &amp;quot;esempi da copiare&amp;quot;) ma presentano dei passaggi di non semplice lettura.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 15:42, 10 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int c;&lt;br /&gt;
        while ((c=getchar())!=EOF)&lt;br /&gt;
                putchar(c);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio tutto ciò che viene preso in input viene messo in output, fino a quando non viene digitato il carattere di End of File (EOF). Solitamente nei sistemi DOS il carattere EOF viene definito come la combinazione di tasti CTRL+Z, mentre nei sistemi basati su Unix si utilizzano i tasti CTRL+D. ([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
Nel caso l'input provenga da file e non da tastiera (ad esempio eseguendo da terminale la riga di comando &amp;quot;./programma0 &amp;lt; testo&amp;quot;), il carattere speciale EOF viene inserito automaticamente alla fine del file &amp;quot;testo&amp;quot;. In questo caso il programma prende in input il contenuto di &amp;quot;testo&amp;quot; e stampa a video (carattere per carattere), il contenuto del file, finchè non riconosce il carattere speciale EOF, che fa terminare il ciclo while.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
questo &amp;amp;egrave; l'esercizio visto in aula. Il punto da notare &amp;amp;egrave; l'uso dell'assegnazione all'interno del controllo del ciclo while. E' una struttura tipica del linguaggio C che semplifica sintatticamente la scrittura del programma.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:02, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
char s1[]=&amp;quot;hello world&amp;quot;;&lt;br /&gt;
char *s2=&amp;quot;hello world&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
void foo(char *s) {&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,s);&lt;br /&gt;
        s[4]=',';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,s);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        foo(s1);&lt;br /&gt;
        foo(s2);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio viene mostrata la differenza tra stringa variabile (s1) e stringa costante (s2). Nel primo caso a tempo di compilazione la stringa costante &amp;quot;hello world&amp;quot; viene copiata passo nella stringa variabile s1 consentendo le normali operazioni di modifica della stringa stessa. Mentre nel secondo caso a tempo di compilazione viene creata la stringa costante &amp;quot;hello world&amp;quot; e memorizzato il suo indirizzo nella variabile s2 NON consentendo le normali operazioni di modifica delle stringa stessa in quanto appunto un costante. ([[User:S.G|S.G]])&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
char t[]=&amp;quot;test&amp;quot;;&lt;br /&gt;
struct st {&lt;br /&gt;
        char s[5];&lt;br /&gt;
        char *t;&lt;br /&gt;
} st0={&amp;quot;test&amp;quot;,t};&lt;br /&gt;
&lt;br /&gt;
void foo (struct st i) {&lt;br /&gt;
        i.s[2]='n';&lt;br /&gt;
        i.t[2]='n';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bar (struct st *i) {&lt;br /&gt;
        i-&amp;gt;s[2]='x';&lt;br /&gt;
        i-&amp;gt;t[2]='x';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t);&lt;br /&gt;
        foo(st0); /* Vengono copiati i valori della struttura st0 in i, le uniche modifiche saranno sul campo i.t in quanto puntatore. */&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t); &lt;br /&gt;
        bar(&amp;amp;st0); /* Viene copiato l'indirizzo della struttura st0 in i, le modifiche vengono apportate su tutti i campi delle struttura. */&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Output del programma:&lt;br /&gt;
&lt;br /&gt;
test test&lt;br /&gt;
&lt;br /&gt;
test tent&lt;br /&gt;
&lt;br /&gt;
text text&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
S&amp;amp;igrave;, ma perch&amp;amp;eacute;? Come &amp;amp;egrave; fatta la struttura st? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:06, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
La struttura st è fatta da un array di 5 caratteri e da un puntatore a caratteri (che viene usato anch'esso per puntare ad un'array di caratteri).&lt;br /&gt;
&lt;br /&gt;
Con la prima chiamata a printf vengono stampati i valori dei campi della struttura non ancora modificati, dal momento che non è stata ancora chiamata nè la funzione foo nè la funzione bar (test test)&lt;br /&gt;
&lt;br /&gt;
In seguito viene passata la struct st0 alla funzione foo. In particolare viene passata alla funzione una COPIA del primo campo e una COPIA del secondo campo; tuttavia essendo il secondo campo della struttura un puntatore, viene passato il valore del puntatore, che è un indirizzo, cioè l'indirizzo a cui si trova l'array t (char t[]=&amp;quot;test&amp;quot;). Per questo motivo viene modificato solo il valore del secondo campo nella struttura st0, infatti quando la funzione termina, la copia del primo campo viene persa, senza aver modificato il valore originale, mentre il valore del secondo campo viene modificato perchè l'abbiamo modificato tramite l'indirizzo. L'output finale sarà quindi: test tent.&lt;br /&gt;
&lt;br /&gt;
Alla chiamata alla funzione bar, viene invece passato l'INDIRIZZO della struttura st0, e per questo quando andiamo a modificare i campi della struttura all'interno della funzione bar, non stiamo modificando una copia di st0, ma stiamo modificando direttamente st0, accedendo tramite puntatore ai suoi singoli campi. Quindi quando bar termina, i valori originali sono stati modificati e l'output risulterà: text text.&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        while (argc &amp;gt; 1) {&lt;br /&gt;
                int i,j;&lt;br /&gt;
                char *s=argv[1];&lt;br /&gt;
                for (i=0, j=strlen(s)-1; i &amp;lt; j; i++, j--)&lt;br /&gt;
                        s[i] ^= s[j], s[j] ^= s[i], s[i] ^= s[j];&lt;br /&gt;
                printf(&amp;quot;%s &amp;quot;,s);&lt;br /&gt;
                argc--;&lt;br /&gt;
                argv++;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio il programma effettua un reverse di tutte le parole che gli vengo date in input ad esclusione di argv[0] che sarebbe il nome del programma, esempio:&lt;br /&gt;
&lt;br /&gt;
INPUT: ./programma3 ciao sistemi operativi&lt;br /&gt;
&lt;br /&gt;
OUTPUT: oaic imetsis ivitarepo&lt;br /&gt;
&lt;br /&gt;
Il punto importante di questo codice è che lo scambio delle singole lettere viene effettuato con l'operatore logico XOR senza cosi avere bisogno di una &amp;quot;variabile di scambio&amp;quot;.&lt;br /&gt;
Qui viene spiegato nel dettaglio il [https://it.wikibooks.org/wiki/C/Variabili,_operatori_e_costanti/Operatori_sui_bit funzionamento dell'operatore logico]&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
== programma 4 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct elem {&lt;br /&gt;
        char *s;&lt;br /&gt;
        struct elem *next;&lt;br /&gt;
};&lt;br /&gt;
struct elem *root=NULL;&lt;br /&gt;
&lt;br /&gt;
void insert(char *s, struct elem **elp) { /* Inserimento in ordine alfabetico */&lt;br /&gt;
        if (*elp &amp;amp;&amp;amp; strcmp((*elp)-&amp;gt;s, s) &amp;lt; 0) /* se la lista elp non è vuota e se (*elp)-&amp;gt;s è alfabeticamente minore di s, inserisce in coda s */&lt;br /&gt;
                insert(s,&amp;amp;((*elp)-&amp;gt;next));&lt;br /&gt;
        else { /* nel caso in cui la lista è vuota o se (*elp)-&amp;gt;s è alfabeticamente maggiore di s, inserisce in testa s */&lt;br /&gt;
                struct elem tmp={s,*elp};&lt;br /&gt;
                struct elem *new=malloc(sizeof(struct elem));&lt;br /&gt;
                *new=tmp;&lt;br /&gt;
                *elp=new;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct elem *print(struct elem *root) { /* stampa l'intera lista, alla fine dealloca root e restituisce NULL */&lt;br /&gt;
        if (root) {&lt;br /&gt;
                printf(&amp;quot;%s &amp;quot;,root-&amp;gt;s);&lt;br /&gt;
                root-&amp;gt;next=print(root-&amp;gt;next);&lt;br /&gt;
                free(root);&lt;br /&gt;
                return NULL;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        for (;argc&amp;gt;1;argc--,argv++) /* Scorre tutti gli elementi in input del programma (tranne il nome stesso del programma), aggiungendoli in una lista */&lt;br /&gt;
                insert(argv[1],&amp;amp;root);&lt;br /&gt;
        root=print(root);&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il programma ordina alfabeticamente gli elementi presi input, esempio: &lt;br /&gt;
&lt;br /&gt;
INPUT: ./programma4 ciao sistemi operativi e macchine virtuali&lt;br /&gt;
&lt;br /&gt;
OUTPUT: ciao e macchine operativi sistemi virtuali&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Per&amp;amp;ograve; ci sono due tecniche diverse per la scrittura di funzioni ricorsive che modificano liste... Chi le spiega? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:08, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
In quanto la lista va modificata, in questo esempio, è stato passato l'indirizzo di memoria del puntatore di testa della lista. Ne verrà quindi usata una copia all'interno della funzione ma, essendo una copia di un indirizzo di memoria, si andrà ugualmente ad agire fisicamente sulla struttura dati.&lt;br /&gt;
La seconda opzione è quella di passare la testa della lista come parametro, così facendo però ne verrà creata una copia. Per rendere quindi effettive le modifiche che avvengono nella funzione, bisogna quindi che la funzione non abbia risultato Void bensì deve ritornare come valore la testa della lista modificata. Nella chiamata della funzione è quindi necessario un assegnamento del tipo: head = func(head);&lt;br /&gt;
&lt;br /&gt;
Alessandro Bandini&lt;br /&gt;
&lt;br /&gt;
==Programma 5==&lt;br /&gt;
Propongo un esempio relativo all'uso dello statement static:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int var;&lt;br /&gt;
&lt;br /&gt;
int foo(){&lt;br /&gt;
	static int var=0;&lt;br /&gt;
	var++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bar(){&lt;br /&gt;
	int var=0;&lt;br /&gt;
	var ++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int foobar(){&lt;br /&gt;
	var++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	int sum1, sum2, sum3;&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum1=foo();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum1);&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum2=bar();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum2);&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum3=foobar();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum3);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output del codice:&lt;br /&gt;
&lt;br /&gt;
100&lt;br /&gt;
&lt;br /&gt;
1&lt;br /&gt;
&lt;br /&gt;
100&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Le tre funzioni ''foo()'', ''bar()'' e ''foobar()'', sebbene si possa pensare agiscano sulla stessa variabile globale intera ''var'', hanno comportamenti diversi proprio perche' non agiscono sulla stessa variabile. Nella funzione ''foo()'', viene ridefinita una nuova variabile intera ''var'' che ha uno scope limitato al solo corpo della funzione (e' come se avesse una &amp;quot;precedenza&amp;quot; maggiore rispetto alla variabile globale); inoltre essa e' definita come ''static'': il valore della varibile non viene quindi salvato nello STACK della funzione bensi' nel segmento DATA, permettendo di avere il valore salvato anche dopo piu' chiamate della funzione.&lt;br /&gt;
&lt;br /&gt;
Il discorso e' leggermente diverso per la funzione ''bar()'': anche qui viene ridefinita la variabile ''var'' ma non in modo static. Il valore di ''var'' e' quindi salvato nello STACK della funzione, che viene ricreato ad ogni chiamata. Sebbene ''bar()'' venga chiamata cento volte, a ''sum2'' viene assegnato solo un incremento, a causa dell'inizializzazione a 0 di ''var'' che avviene per ogni chiamata.&lt;br /&gt;
&lt;br /&gt;
Infine, all'interno della funzione ''foobar()'' non viene definita una nuova variabile, quindi la ''var'' usata nel corpo e' la variabile globale definita in precedenza. Similmente ad una variabile static, anche il valore di una variabile globale viene memorizzato nel segmento DATA del programma, ed il cui valore rimane in memoria nonostante le successive chiamate della funzione.&lt;br /&gt;
&lt;br /&gt;
Matteo Del Vecchio&lt;br /&gt;
&lt;br /&gt;
==Programma 6==&lt;br /&gt;
Challenge: Cosa fa questo programma (progettato per processori atmega8/88/168 etc)?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#ifdef ATMEGA88&lt;br /&gt;
#define F_CPU 8000000UL  // 8 MHz&lt;br /&gt;
#else&lt;br /&gt;
#define F_CPU 1000000UL  // 1 MHz&lt;br /&gt;
#endif&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void delay_ms(unsigned int ms)&lt;br /&gt;
{&lt;br /&gt;
        while(ms){&lt;br /&gt;
                _delay_ms(0.96);&lt;br /&gt;
                ms--;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#define DMASK 0x07&lt;br /&gt;
#define TWSR_STATUS_MASK 0xF8&lt;br /&gt;
#define TWCR_CMD_MASK 0x0F&lt;br /&gt;
&lt;br /&gt;
unsigned char newB;&lt;br /&gt;
unsigned char oldB;&lt;br /&gt;
unsigned char diffB;&lt;br /&gt;
unsigned char status;&lt;br /&gt;
unsigned char unstable;&lt;br /&gt;
unsigned char step;&lt;br /&gt;
unsigned char value;&lt;br /&gt;
unsigned char d0,d1,d2,d3,d4,d5,d6,d7,d8;&lt;br /&gt;
&lt;br /&gt;
static unsigned char i2cs_addr;&lt;br /&gt;
&lt;br /&gt;
void i2cs_init(void)&lt;br /&gt;
{&lt;br /&gt;
        TWCR = 1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA | 1&amp;lt;&amp;lt;TWEN | 1&amp;lt;&amp;lt;TWIE;&lt;br /&gt;
        TWAR = i2cs_addr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void i2cs_command(unsigned char comm)&lt;br /&gt;
{&lt;br /&gt;
        switch (comm &amp;amp; 0xF8) {&lt;br /&gt;
                case 0x80:&lt;br /&gt;
                        if (step)&lt;br /&gt;
                                status &amp;amp;= ~(1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        else&lt;br /&gt;
                                PORTD &amp;amp;= ~(1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        break;&lt;br /&gt;
                case 0x88:&lt;br /&gt;
                        if (step)&lt;br /&gt;
                                status |= (1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        else&lt;br /&gt;
                                PORTD |= (1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        break;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TWI_vect)&lt;br /&gt;
{&lt;br /&gt;
        unsigned char i2c_status= TWSR &amp;amp; TWSR_STATUS_MASK;&lt;br /&gt;
        switch (i2c_status) {&lt;br /&gt;
                case TW_SR_DATA_ACK:&lt;br /&gt;
                        i2cs_command(TWDR);&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
                case TW_ST_SLA_ACK:&lt;br /&gt;
                case TW_ST_DATA_ACK:&lt;br /&gt;
                        TWDR = status;&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
                default:&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
        DDRD = 0xFF;&lt;br /&gt;
        PORTB = 0xFF;&lt;br /&gt;
        PORTC = 0x0F;&lt;br /&gt;
        delay_ms(10);&lt;br /&gt;
        i2cs_addr= (0x20 | ((~PINC &amp;amp; 0x0F) &amp;lt;&amp;lt; 1));&lt;br /&gt;
        step = (i2cs_addr &amp;amp; 0x10) == 0;&lt;br /&gt;
        i2cs_init();&lt;br /&gt;
        sei();&lt;br /&gt;
        while (1) {&lt;br /&gt;
                delay_ms(1);&lt;br /&gt;
                oldB=newB;&lt;br /&gt;
                newB=~PINB;&lt;br /&gt;
                diffB=oldB ^ newB;&lt;br /&gt;
                unstable=0;&lt;br /&gt;
                if (diffB &amp;amp; 0x01) d0 = 1; else d0++; &lt;br /&gt;
                if (diffB &amp;amp; 0x02) d1 = 1; else d1++;&lt;br /&gt;
                if (diffB &amp;amp; 0x04) d2 = 1; else d2++;&lt;br /&gt;
                if (diffB &amp;amp; 0x08) d3 = 1; else d3++;&lt;br /&gt;
                if (diffB &amp;amp; 0x10) d4 = 1; else d4++;&lt;br /&gt;
                if (diffB &amp;amp; 0x20) d5 = 1; else d5++;&lt;br /&gt;
                if (diffB &amp;amp; 0x40) d6 = 1; else d6++;&lt;br /&gt;
                if (diffB &amp;amp; 0x80) d7 = 1; else d7++;&lt;br /&gt;
                if(d0 &amp;amp; DMASK) unstable |= 0x01;&lt;br /&gt;
                if(d1 &amp;amp; DMASK) unstable |= 0x02;&lt;br /&gt;
                if(d2 &amp;amp; DMASK) unstable |= 0x04;&lt;br /&gt;
                if(d3 &amp;amp; DMASK) unstable |= 0x08;&lt;br /&gt;
                if(d4 &amp;amp; DMASK) unstable |= 0x10;&lt;br /&gt;
                if(d5 &amp;amp; DMASK) unstable |= 0x20;&lt;br /&gt;
                if(d6 &amp;amp; DMASK) unstable |= 0x40;&lt;br /&gt;
                if(d7 &amp;amp; DMASK) unstable |= 0x80;&lt;br /&gt;
                if (step) {&lt;br /&gt;
                        status ^= (newB &amp;amp; ~value &amp;amp; ~unstable);&lt;br /&gt;
                        value = (value &amp;amp; unstable) | (newB &amp;amp; ~unstable);&lt;br /&gt;
                } else&lt;br /&gt;
                        status = (status &amp;amp; unstable) | (newB &amp;amp; ~unstable);&lt;br /&gt;
                if (step)&lt;br /&gt;
                        PORTD=status;&lt;br /&gt;
        }&lt;br /&gt;
        return(0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:06, 21 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
==Programma 7==&lt;br /&gt;
Guardate queste costanti predefinite. Come le utilizzereste?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  printf(&amp;quot;%s: line %d\n&amp;quot;,__FILE__,__LINE__);&lt;br /&gt;
  printf(&amp;quot;built %s %s\n&amp;quot;,__DATE__,__TIME__);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 8==&lt;br /&gt;
Un &amp;quot;effetto speciale&amp;quot; del preprocessore:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#define ik(x) int k##x = x&lt;br /&gt;
#define ck(x) char *k##x = #x&lt;br /&gt;
&lt;br /&gt;
ik(0);&lt;br /&gt;
ik(1);&lt;br /&gt;
ik(2);&lt;br /&gt;
ck(tricky);&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  printf(&amp;quot;%d %d %d %s\n&amp;quot;, k0, k1, k2, ktricky);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il programma stampa: 0 1 2 tricky&lt;br /&gt;
&lt;br /&gt;
Questo e' dovuto al fatto che il preprocessore sostituisce ogni occorrenza di ik(x) con int kx = x; Lo stesso avviene per la stringa tricky. Infatti se andiamo a guardare il programma facendo solo la fase di preproccessing dando il comando gcc -E [...] notiamo che diventa cosi':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int k0 = 0;&lt;br /&gt;
int k1 = 1;&lt;br /&gt;
int k2 = 2;&lt;br /&gt;
char *ktricky = &amp;quot;tricky&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
      printf(&amp;quot;%d %d %d %s\n&amp;quot;, k0, k1, k2, ktricky);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'operatore ## concatena due argomenti senza lasciare spazi bianchi tra di loro, in questo caso concatena k ad x.&lt;br /&gt;
&amp;lt;br/&amp;gt;Non importa che ci sia uno spazio tra k e x. Vedi [http://www.cplusplus.com/doc/oldtutorial/preprocessor/]&lt;br /&gt;
&lt;br /&gt;
[[User:Aletri|Aletri]] ([[User talk:Aletri|talk]])&lt;br /&gt;
&lt;br /&gt;
==Programma 9==&lt;br /&gt;
Ecco un esempio di uso della libreria stdarg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void intprint(int n, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list ap;&lt;br /&gt;
&lt;br /&gt;
  va_start(ap, n);&lt;br /&gt;
  while (n&amp;gt;0) {&lt;br /&gt;
    int i;&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;,va_arg(ap,int));&lt;br /&gt;
    n--;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  va_end(ap);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv) {&lt;br /&gt;
  intprint(3,1,2,3);&lt;br /&gt;
  intprint(5,1,2,3,4,5);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 10==&lt;br /&gt;
Un po' di trucchi con le macro e le funzioni a numero variabile di parametri con passaggio di liste di parametri.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define debugprintf(fmt, ...) private_debugprintf((fmt),__FILE__,__LINE__, ##__VA_ARGS__)&lt;br /&gt;
&lt;br /&gt;
int private_debugprintf(const char *fmt, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list ap;&lt;br /&gt;
  char *newfmt;&lt;br /&gt;
  int rv;&lt;br /&gt;
&lt;br /&gt;
  va_start(ap, fmt);&lt;br /&gt;
  asprintf(&amp;amp;newfmt,&amp;quot;File %%s Line %%d %s&amp;quot;,fmt);&lt;br /&gt;
  rv=vfprintf(stderr, newfmt, ap);&lt;br /&gt;
  free(newfmt);&lt;br /&gt;
  return rv;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char *name=&amp;quot;douglas adams&amp;quot;;&lt;br /&gt;
int value=42;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  debugprintf(&amp;quot;hello world, bug!\n&amp;quot;);&lt;br /&gt;
  debugprintf(&amp;quot;string: %s int: %d\n&amp;quot;,name,value);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 11==&lt;br /&gt;
getopt e getopt_long sono molto utili.... ecco un esempio. Cosa fa questo programma?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;getopt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libgen.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void usage(char *progname) {&lt;br /&gt;
  fprintf(stderr,&lt;br /&gt;
      &amp;quot;Usage:\n&amp;quot;&lt;br /&gt;
      &amp;quot;\t%s [-m num] [-r] args...\n&amp;quot;&lt;br /&gt;
      &amp;quot;\t%s [--mul num] [--rev] args...\n&amp;quot;,progname,progname);&lt;br /&gt;
  exit(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  int c, oindex;&lt;br /&gt;
  int rev=0;&lt;br /&gt;
  int mul=1;&lt;br /&gt;
  static struct option long_options[] = {&lt;br /&gt;
    {&amp;quot;mul&amp;quot;, required_argument, 0, 'm'},&lt;br /&gt;
    {&amp;quot;rev&amp;quot;, no_argument, 0, 'r'}};&lt;br /&gt;
  while ((c = getopt_long(argc, argv, &amp;quot;m:r&amp;quot;,&lt;br /&gt;
          long_options, &amp;amp;oindex)) &amp;gt; 0) {&lt;br /&gt;
    switch (c) {&lt;br /&gt;
      case 'm': mul = atoi(optarg);&lt;br /&gt;
                break;&lt;br /&gt;
      case 'r': rev = 1;&lt;br /&gt;
                break;&lt;br /&gt;
      default:&lt;br /&gt;
                usage(basename(argv[0]));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  for (; mul&amp;gt;0; mul--) {&lt;br /&gt;
    if (rev) {&lt;br /&gt;
      for(oindex=argc-1; oindex&amp;gt;=optind; oindex--)&lt;br /&gt;
        printf(&amp;quot;%s &amp;quot;,argv[oindex]);&lt;br /&gt;
    } else {&lt;br /&gt;
      for(oindex=optind; oindex&amp;lt;argc; oindex++)&lt;br /&gt;
        printf(&amp;quot;%s &amp;quot;,argv[oindex]);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_lettura_di_codice_C&amp;diff=1255</id>
		<title>Esercizi di lettura di codice C</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_lettura_di_codice_C&amp;diff=1255"/>
		<updated>2015-11-07T20:19:05Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Soluzione programma 8&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questi programmi non sono necessariamente stilisticamente belli (non sono &amp;quot;esempi da copiare&amp;quot;) ma presentano dei passaggi di non semplice lettura.&lt;br /&gt;
&lt;br /&gt;
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).&lt;br /&gt;
&lt;br /&gt;
Ovviamente potete proporre ulteriori esempi.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 15:42, 10 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== programma 0 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int c;&lt;br /&gt;
        while ((c=getchar())!=EOF)&lt;br /&gt;
                putchar(c);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio tutto ciò che viene preso in input viene messo in output, fino a quando non viene digitato il carattere di End of File (EOF). Solitamente nei sistemi DOS il carattere EOF viene definito come la combinazione di tasti CTRL+Z, mentre nei sistemi basati su Unix si utilizzano i tasti CTRL+D. ([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
Nel caso l'input provenga da file e non da tastiera (ad esempio eseguendo da terminale la riga di comando &amp;quot;./programma0 &amp;lt; testo&amp;quot;), il carattere speciale EOF viene inserito automaticamente alla fine del file &amp;quot;testo&amp;quot;. In questo caso il programma prende in input il contenuto di &amp;quot;testo&amp;quot; e stampa a video (carattere per carattere), il contenuto del file, finchè non riconosce il carattere speciale EOF, che fa terminare il ciclo while.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
questo &amp;amp;egrave; l'esercizio visto in aula. Il punto da notare &amp;amp;egrave; l'uso dell'assegnazione all'interno del controllo del ciclo while. E' una struttura tipica del linguaggio C che semplifica sintatticamente la scrittura del programma.&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:02, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
== programma 1 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
char s1[]=&amp;quot;hello world&amp;quot;;&lt;br /&gt;
char *s2=&amp;quot;hello world&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
void foo(char *s) {&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,s);&lt;br /&gt;
        s[4]=',';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,s);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        foo(s1);&lt;br /&gt;
        foo(s2);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio viene mostrata la differenza tra stringa variabile (s1) e stringa costante (s2). Nel primo caso a tempo di compilazione la stringa costante &amp;quot;hello world&amp;quot; viene copiata passo nella stringa variabile s1 consentendo le normali operazioni di modifica della stringa stessa. Mentre nel secondo caso a tempo di compilazione viene creata la stringa costante &amp;quot;hello world&amp;quot; e memorizzato il suo indirizzo nella variabile s2 NON consentendo le normali operazioni di modifica delle stringa stessa in quanto appunto un costante. ([[User:S.G|S.G]])&lt;br /&gt;
== programma 2 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
char t[]=&amp;quot;test&amp;quot;;&lt;br /&gt;
struct st {&lt;br /&gt;
        char s[5];&lt;br /&gt;
        char *t;&lt;br /&gt;
} st0={&amp;quot;test&amp;quot;,t};&lt;br /&gt;
&lt;br /&gt;
void foo (struct st i) {&lt;br /&gt;
        i.s[2]='n';&lt;br /&gt;
        i.t[2]='n';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bar (struct st *i) {&lt;br /&gt;
        i-&amp;gt;s[2]='x';&lt;br /&gt;
        i-&amp;gt;t[2]='x';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t);&lt;br /&gt;
        foo(st0); /* Vengono copiati i valori della struttura st0 in i, le uniche modifiche saranno sul campo i.t in quanto puntatore. */&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t); &lt;br /&gt;
        bar(&amp;amp;st0); /* Viene copiato l'indirizzo della struttura st0 in i, le modifiche vengono apportate su tutti i campi delle struttura. */&lt;br /&gt;
        printf(&amp;quot;%s %s\n&amp;quot;,st0.s,st0.t);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Output del programma:&lt;br /&gt;
&lt;br /&gt;
test test&lt;br /&gt;
&lt;br /&gt;
test tent&lt;br /&gt;
&lt;br /&gt;
text text&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
S&amp;amp;igrave;, ma perch&amp;amp;eacute;? Come &amp;amp;egrave; fatta la struttura st? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:06, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
La struttura st è fatta da un array di 5 caratteri e da un puntatore a caratteri (che viene usato anch'esso per puntare ad un'array di caratteri).&lt;br /&gt;
&lt;br /&gt;
Con la prima chiamata a printf vengono stampati i valori dei campi della struttura non ancora modificati, dal momento che non è stata ancora chiamata nè la funzione foo nè la funzione bar (test test)&lt;br /&gt;
&lt;br /&gt;
In seguito viene passata la struct st0 alla funzione foo. In particolare viene passata alla funzione una COPIA del primo campo e una COPIA del secondo campo; tuttavia essendo il secondo campo della struttura un puntatore, viene passato il valore del puntatore, che è un indirizzo, cioè l'indirizzo a cui si trova l'array t (char t[]=&amp;quot;test&amp;quot;). Per questo motivo viene modificato solo il valore del secondo campo nella struttura st0, infatti quando la funzione termina, la copia del primo campo viene persa, senza aver modificato il valore originale, mentre il valore del secondo campo viene modificato perchè l'abbiamo modificato tramite l'indirizzo. L'output finale sarà quindi: test tent.&lt;br /&gt;
&lt;br /&gt;
Alla chiamata alla funzione bar, viene invece passato l'INDIRIZZO della struttura st0, e per questo quando andiamo a modificare i campi della struttura all'interno della funzione bar, non stiamo modificando una copia di st0, ma stiamo modificando direttamente st0, accedendo tramite puntatore ai suoi singoli campi. Quindi quando bar termina, i valori originali sono stati modificati e l'output risulterà: text text.&lt;br /&gt;
&lt;br /&gt;
([[User:Alessio|Alessio]])&lt;br /&gt;
&lt;br /&gt;
== programma 3 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        while (argc &amp;gt; 1) {&lt;br /&gt;
                int i,j;&lt;br /&gt;
                char *s=argv[1];&lt;br /&gt;
                for (i=0, j=strlen(s)-1; i &amp;lt; j; i++, j--)&lt;br /&gt;
                        s[i] ^= s[j], s[j] ^= s[i], s[i] ^= s[j];&lt;br /&gt;
                printf(&amp;quot;%s &amp;quot;,s);&lt;br /&gt;
                argc--;&lt;br /&gt;
                argv++;&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In questo esempio il programma effettua un reverse di tutte le parole che gli vengo date in input ad esclusione di argv[0] che sarebbe il nome del programma, esempio:&lt;br /&gt;
&lt;br /&gt;
INPUT: ./programma3 ciao sistemi operativi&lt;br /&gt;
&lt;br /&gt;
OUTPUT: oaic imetsis ivitarepo&lt;br /&gt;
&lt;br /&gt;
Il punto importante di questo codice è che lo scambio delle singole lettere viene effettuato con l'operatore logico XOR senza cosi avere bisogno di una &amp;quot;variabile di scambio&amp;quot;.&lt;br /&gt;
Qui viene spiegato nel dettaglio il [https://it.wikibooks.org/wiki/C/Variabili,_operatori_e_costanti/Operatori_sui_bit funzionamento dell'operatore logico]&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
== programma 4 ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct elem {&lt;br /&gt;
        char *s;&lt;br /&gt;
        struct elem *next;&lt;br /&gt;
};&lt;br /&gt;
struct elem *root=NULL;&lt;br /&gt;
&lt;br /&gt;
void insert(char *s, struct elem **elp) { /* Inserimento in ordine alfabetico */&lt;br /&gt;
        if (*elp &amp;amp;&amp;amp; strcmp((*elp)-&amp;gt;s, s) &amp;lt; 0) /* se la lista elp non è vuota e se (*elp)-&amp;gt;s è alfabeticamente minore di s, inserisce in coda s */&lt;br /&gt;
                insert(s,&amp;amp;((*elp)-&amp;gt;next));&lt;br /&gt;
        else { /* nel caso in cui la lista è vuota o se (*elp)-&amp;gt;s è alfabeticamente maggiore di s, inserisce in testa s */&lt;br /&gt;
                struct elem tmp={s,*elp};&lt;br /&gt;
                struct elem *new=malloc(sizeof(struct elem));&lt;br /&gt;
                *new=tmp;&lt;br /&gt;
                *elp=new;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct elem *print(struct elem *root) { /* stampa l'intera lista, alla fine dealloca root e restituisce NULL */&lt;br /&gt;
        if (root) {&lt;br /&gt;
                printf(&amp;quot;%s &amp;quot;,root-&amp;gt;s);&lt;br /&gt;
                root-&amp;gt;next=print(root-&amp;gt;next);&lt;br /&gt;
                free(root);&lt;br /&gt;
                return NULL;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        for (;argc&amp;gt;1;argc--,argv++) /* Scorre tutti gli elementi in input del programma (tranne il nome stesso del programma), aggiungendoli in una lista */&lt;br /&gt;
                insert(argv[1],&amp;amp;root);&lt;br /&gt;
        root=print(root);&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il programma ordina alfabeticamente gli elementi presi input, esempio: &lt;br /&gt;
&lt;br /&gt;
INPUT: ./programma4 ciao sistemi operativi e macchine virtuali&lt;br /&gt;
&lt;br /&gt;
OUTPUT: ciao e macchine operativi sistemi virtuali&lt;br /&gt;
&lt;br /&gt;
([[User:S.G|S.G]])&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Per&amp;amp;ograve; ci sono due tecniche diverse per la scrittura di funzioni ricorsive che modificano liste... Chi le spiega? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:08, 17 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
In quanto la lista va modificata, in questo esempio, è stato passato l'indirizzo di memoria del puntatore di testa della lista. Ne verrà quindi usata una copia all'interno della funzione ma, essendo una copia di un indirizzo di memoria, si andrà ugualmente ad agire fisicamente sulla struttura dati.&lt;br /&gt;
La seconda opzione è quella di passare la testa della lista come parametro, così facendo però ne verrà creata una copia. Per rendere quindi effettive le modifiche che avvengono nella funzione, bisogna quindi che la funzione non abbia risultato Void bensì deve ritornare come valore la testa della lista modificata. Nella chiamata della funzione è quindi necessario un assegnamento del tipo: head = func(head);&lt;br /&gt;
&lt;br /&gt;
Alessandro Bandini&lt;br /&gt;
&lt;br /&gt;
==Programma 5==&lt;br /&gt;
Propongo un esempio relativo all'uso dello statement static:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int var;&lt;br /&gt;
&lt;br /&gt;
int foo(){&lt;br /&gt;
	static int var=0;&lt;br /&gt;
	var++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bar(){&lt;br /&gt;
	int var=0;&lt;br /&gt;
	var ++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int foobar(){&lt;br /&gt;
	var++;&lt;br /&gt;
	return var;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]){&lt;br /&gt;
	int sum1, sum2, sum3;&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum1=foo();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum1);&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum2=bar();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum2);&lt;br /&gt;
	for(i=0;i&amp;lt;100;i++){&lt;br /&gt;
		sum3=foobar();&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, sum3);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output del codice:&lt;br /&gt;
&lt;br /&gt;
100&lt;br /&gt;
&lt;br /&gt;
1&lt;br /&gt;
&lt;br /&gt;
100&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Le tre funzioni ''foo()'', ''bar()'' e ''foobar()'', sebbene si possa pensare agiscano sulla stessa variabile globale intera ''var'', hanno comportamenti diversi proprio perche' non agiscono sulla stessa variabile. Nella funzione ''foo()'', viene ridefinita una nuova variabile intera ''var'' che ha uno scope limitato al solo corpo della funzione (e' come se avesse una &amp;quot;precedenza&amp;quot; maggiore rispetto alla variabile globale); inoltre essa e' definita come ''static'': il valore della varibile non viene quindi salvato nello STACK della funzione bensi' nel segmento DATA, permettendo di avere il valore salvato anche dopo piu' chiamate della funzione.&lt;br /&gt;
&lt;br /&gt;
Il discorso e' leggermente diverso per la funzione ''bar()'': anche qui viene ridefinita la variabile ''var'' ma non in modo static. Il valore di ''var'' e' quindi salvato nello STACK della funzione, che viene ricreato ad ogni chiamata. Sebbene ''bar()'' venga chiamata cento volte, a ''sum2'' viene assegnato solo un incremento, a causa dell'inizializzazione a 0 di ''var'' che avviene per ogni chiamata.&lt;br /&gt;
&lt;br /&gt;
Infine, all'interno della funzione ''foobar()'' non viene definita una nuova variabile, quindi la ''var'' usata nel corpo e' la variabile globale definita in precedenza. Similmente ad una variabile static, anche il valore di una variabile globale viene memorizzato nel segmento DATA del programma, ed il cui valore rimane in memoria nonostante le successive chiamate della funzione.&lt;br /&gt;
&lt;br /&gt;
Matteo Del Vecchio&lt;br /&gt;
&lt;br /&gt;
==Programma 6==&lt;br /&gt;
Challenge: Cosa fa questo programma (progettato per processori atmega8/88/168 etc)?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#ifdef ATMEGA88&lt;br /&gt;
#define F_CPU 8000000UL  // 8 MHz&lt;br /&gt;
#else&lt;br /&gt;
#define F_CPU 1000000UL  // 1 MHz&lt;br /&gt;
#endif&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void delay_ms(unsigned int ms)&lt;br /&gt;
{&lt;br /&gt;
        while(ms){&lt;br /&gt;
                _delay_ms(0.96);&lt;br /&gt;
                ms--;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#define DMASK 0x07&lt;br /&gt;
#define TWSR_STATUS_MASK 0xF8&lt;br /&gt;
#define TWCR_CMD_MASK 0x0F&lt;br /&gt;
&lt;br /&gt;
unsigned char newB;&lt;br /&gt;
unsigned char oldB;&lt;br /&gt;
unsigned char diffB;&lt;br /&gt;
unsigned char status;&lt;br /&gt;
unsigned char unstable;&lt;br /&gt;
unsigned char step;&lt;br /&gt;
unsigned char value;&lt;br /&gt;
unsigned char d0,d1,d2,d3,d4,d5,d6,d7,d8;&lt;br /&gt;
&lt;br /&gt;
static unsigned char i2cs_addr;&lt;br /&gt;
&lt;br /&gt;
void i2cs_init(void)&lt;br /&gt;
{&lt;br /&gt;
        TWCR = 1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA | 1&amp;lt;&amp;lt;TWEN | 1&amp;lt;&amp;lt;TWIE;&lt;br /&gt;
        TWAR = i2cs_addr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void i2cs_command(unsigned char comm)&lt;br /&gt;
{&lt;br /&gt;
        switch (comm &amp;amp; 0xF8) {&lt;br /&gt;
                case 0x80:&lt;br /&gt;
                        if (step)&lt;br /&gt;
                                status &amp;amp;= ~(1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        else&lt;br /&gt;
                                PORTD &amp;amp;= ~(1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        break;&lt;br /&gt;
                case 0x88:&lt;br /&gt;
                        if (step)&lt;br /&gt;
                                status |= (1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        else&lt;br /&gt;
                                PORTD |= (1&amp;lt;&amp;lt;(comm &amp;amp; 0x07));&lt;br /&gt;
                        break;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TWI_vect)&lt;br /&gt;
{&lt;br /&gt;
        unsigned char i2c_status= TWSR &amp;amp; TWSR_STATUS_MASK;&lt;br /&gt;
        switch (i2c_status) {&lt;br /&gt;
                case TW_SR_DATA_ACK:&lt;br /&gt;
                        i2cs_command(TWDR);&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
                case TW_ST_SLA_ACK:&lt;br /&gt;
                case TW_ST_DATA_ACK:&lt;br /&gt;
                        TWDR = status;&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
                default:&lt;br /&gt;
                        TWCR = (TWCR &amp;amp; TWCR_CMD_MASK) |  1&amp;lt;&amp;lt;TWINT | 1&amp;lt;&amp;lt;TWEA;&lt;br /&gt;
                        break;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
        DDRD = 0xFF;&lt;br /&gt;
        PORTB = 0xFF;&lt;br /&gt;
        PORTC = 0x0F;&lt;br /&gt;
        delay_ms(10);&lt;br /&gt;
        i2cs_addr= (0x20 | ((~PINC &amp;amp; 0x0F) &amp;lt;&amp;lt; 1));&lt;br /&gt;
        step = (i2cs_addr &amp;amp; 0x10) == 0;&lt;br /&gt;
        i2cs_init();&lt;br /&gt;
        sei();&lt;br /&gt;
        while (1) {&lt;br /&gt;
                delay_ms(1);&lt;br /&gt;
                oldB=newB;&lt;br /&gt;
                newB=~PINB;&lt;br /&gt;
                diffB=oldB ^ newB;&lt;br /&gt;
                unstable=0;&lt;br /&gt;
                if (diffB &amp;amp; 0x01) d0 = 1; else d0++; &lt;br /&gt;
                if (diffB &amp;amp; 0x02) d1 = 1; else d1++;&lt;br /&gt;
                if (diffB &amp;amp; 0x04) d2 = 1; else d2++;&lt;br /&gt;
                if (diffB &amp;amp; 0x08) d3 = 1; else d3++;&lt;br /&gt;
                if (diffB &amp;amp; 0x10) d4 = 1; else d4++;&lt;br /&gt;
                if (diffB &amp;amp; 0x20) d5 = 1; else d5++;&lt;br /&gt;
                if (diffB &amp;amp; 0x40) d6 = 1; else d6++;&lt;br /&gt;
                if (diffB &amp;amp; 0x80) d7 = 1; else d7++;&lt;br /&gt;
                if(d0 &amp;amp; DMASK) unstable |= 0x01;&lt;br /&gt;
                if(d1 &amp;amp; DMASK) unstable |= 0x02;&lt;br /&gt;
                if(d2 &amp;amp; DMASK) unstable |= 0x04;&lt;br /&gt;
                if(d3 &amp;amp; DMASK) unstable |= 0x08;&lt;br /&gt;
                if(d4 &amp;amp; DMASK) unstable |= 0x10;&lt;br /&gt;
                if(d5 &amp;amp; DMASK) unstable |= 0x20;&lt;br /&gt;
                if(d6 &amp;amp; DMASK) unstable |= 0x40;&lt;br /&gt;
                if(d7 &amp;amp; DMASK) unstable |= 0x80;&lt;br /&gt;
                if (step) {&lt;br /&gt;
                        status ^= (newB &amp;amp; ~value &amp;amp; ~unstable);&lt;br /&gt;
                        value = (value &amp;amp; unstable) | (newB &amp;amp; ~unstable);&lt;br /&gt;
                } else&lt;br /&gt;
                        status = (status &amp;amp; unstable) | (newB &amp;amp; ~unstable);&lt;br /&gt;
                if (step)&lt;br /&gt;
                        PORTD=status;&lt;br /&gt;
        }&lt;br /&gt;
        return(0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 08:06, 21 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
==Programma 7==&lt;br /&gt;
Guardate queste costanti predefinite. Come le utilizzereste?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  printf(&amp;quot;%s: line %d\n&amp;quot;,__FILE__,__LINE__);&lt;br /&gt;
  printf(&amp;quot;built %s %s\n&amp;quot;,__DATE__,__TIME__);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 8==&lt;br /&gt;
Un &amp;quot;effetto speciale&amp;quot; del preprocessore:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#define ik(x) int k##x = x&lt;br /&gt;
#define ck(x) char *k##x = #x&lt;br /&gt;
&lt;br /&gt;
ik(0);&lt;br /&gt;
ik(1);&lt;br /&gt;
ik(2);&lt;br /&gt;
ck(tricky);&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  printf(&amp;quot;%d %d %d %s\n&amp;quot;, k0, k1, k2, ktricky);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il programma stampa: 0 1 2 tricky&lt;br /&gt;
&lt;br /&gt;
Questo e' dovuto al fatto che il preprocessore sostituisce ogni occorrenza di ik(x) con int k##x = x; Lo stesso avviene per la stringa tricky. Infatti se andiamo a guardare il programma facendo solo la fase di preproccessing dando il comando gcc -E [...] notiamo che diventa cosi':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int k0 = 0;&lt;br /&gt;
int k1 = 1;&lt;br /&gt;
int k2 = 2;&lt;br /&gt;
char *ktricky = &amp;quot;tricky&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
      printf(&amp;quot;%d %d %d %s\n&amp;quot;, k0, k1, k2, ktricky);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'operatore ## concatena due argomenti senza lasciare spazi bianchi tra di loro, in questo caso concatena k ad x.&lt;br /&gt;
&amp;lt;br/&amp;gt;Non importa che ci sia uno spazio tra k e x. Vedi [http://www.cplusplus.com/doc/oldtutorial/preprocessor/]&lt;br /&gt;
&lt;br /&gt;
[[User:Aletri|Aletri]] ([[User talk:Aletri|talk]])&lt;br /&gt;
&lt;br /&gt;
==Programma 9==&lt;br /&gt;
Ecco un esempio di uso della libreria stdarg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void intprint(int n, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list ap;&lt;br /&gt;
&lt;br /&gt;
  va_start(ap, n);&lt;br /&gt;
  while (n&amp;gt;0) {&lt;br /&gt;
    int i;&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;,va_arg(ap,int));&lt;br /&gt;
    n--;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  va_end(ap);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv) {&lt;br /&gt;
  intprint(3,1,2,3);&lt;br /&gt;
  intprint(5,1,2,3,4,5);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 10==&lt;br /&gt;
Un po' di trucchi con le macro e le funzioni a numero variabile di parametri con passaggio di liste di parametri.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define debugprintf(fmt, ...) private_debugprintf((fmt),__FILE__,__LINE__, ##__VA_ARGS__)&lt;br /&gt;
&lt;br /&gt;
int private_debugprintf(const char *fmt, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list ap;&lt;br /&gt;
  char *newfmt;&lt;br /&gt;
  int rv;&lt;br /&gt;
&lt;br /&gt;
  va_start(ap, fmt);&lt;br /&gt;
  asprintf(&amp;amp;newfmt,&amp;quot;File %%s Line %%d %s&amp;quot;,fmt);&lt;br /&gt;
  rv=vfprintf(stderr, newfmt, ap);&lt;br /&gt;
  free(newfmt);&lt;br /&gt;
  return rv;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char *name=&amp;quot;douglas adams&amp;quot;;&lt;br /&gt;
int value=42;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  debugprintf(&amp;quot;hello world, bug!\n&amp;quot;);&lt;br /&gt;
  debugprintf(&amp;quot;string: %s int: %d\n&amp;quot;,name,value);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programma 11==&lt;br /&gt;
getopt e getopt_long sono molto utili.... ecco un esempio. Cosa fa questo programma?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;getopt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libgen.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void usage(char *progname) {&lt;br /&gt;
  fprintf(stderr,&lt;br /&gt;
      &amp;quot;Usage:\n&amp;quot;&lt;br /&gt;
      &amp;quot;\t%s [-m num] [-r] args...\n&amp;quot;&lt;br /&gt;
      &amp;quot;\t%s [--mul num] [--rev] args...\n&amp;quot;,progname,progname);&lt;br /&gt;
  exit(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  int c, oindex;&lt;br /&gt;
  int rev=0;&lt;br /&gt;
  int mul=1;&lt;br /&gt;
  static struct option long_options[] = {&lt;br /&gt;
    {&amp;quot;mul&amp;quot;, required_argument, 0, 'm'},&lt;br /&gt;
    {&amp;quot;rev&amp;quot;, no_argument, 0, 'r'}};&lt;br /&gt;
  while ((c = getopt_long(argc, argv, &amp;quot;m:r&amp;quot;,&lt;br /&gt;
          long_options, &amp;amp;oindex)) &amp;gt; 0) {&lt;br /&gt;
    switch (c) {&lt;br /&gt;
      case 'm': mul = atoi(optarg);&lt;br /&gt;
                break;&lt;br /&gt;
      case 'r': rev = 1;&lt;br /&gt;
                break;&lt;br /&gt;
      default:&lt;br /&gt;
                usage(basename(argv[0]));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  for (; mul&amp;gt;0; mul--) {&lt;br /&gt;
    if (rev) {&lt;br /&gt;
      for(oindex=argc-1; oindex&amp;gt;=optind; oindex--)&lt;br /&gt;
        printf(&amp;quot;%s &amp;quot;,argv[oindex]);&lt;br /&gt;
    } else {&lt;br /&gt;
      for(oindex=optind; oindex&amp;lt;argc; oindex++)&lt;br /&gt;
        printf(&amp;quot;%s &amp;quot;,argv[oindex]);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1254</id>
		<title>Sistemi Operativi:Community portal</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1254"/>
		<updated>2015-11-05T09:52:45Z</updated>

		<summary type="html">&lt;p&gt;Aletri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pensavo di utilizzare questa pagina del community portal per scambiarci suggerimenti per quanto riguarda la parte di elettronica. &amp;lt;br/&amp;gt;&lt;br /&gt;
[[User:Aletri|Aletri]] ([[User talk:Aletri|talk]]) 09:58, 5 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
*[[RaspberryPi - Interfacciarsi con un relay, esempio]]&lt;br /&gt;
*[[Quale numero di GPIO usare?]]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Quale_numero_di_GPIO_usare%3F&amp;diff=1253</id>
		<title>Quale numero di GPIO usare?</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Quale_numero_di_GPIO_usare%3F&amp;diff=1253"/>
		<updated>2015-11-05T09:51:30Z</updated>

		<summary type="html">&lt;p&gt;Aletri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Il problema principale che mi sono posto andando a guardare la gpio map del Raspberry è stato: ho due numeri, quale dei due devo utilizzare?&lt;br /&gt;
&lt;br /&gt;
Esistono due diversi modi per interfacciarsi con i GPIO:&lt;br /&gt;
#Notazione BOARD&lt;br /&gt;
#Notazione BROADCOM (BCM)&lt;br /&gt;
&lt;br /&gt;
;Notazione BOARD&lt;br /&gt;
:La notazione BOARD e' quella piu semplice ed e' quella che (nella maggior parte dei casi) garantisce una maggiore portabilita' tra i vari modelli di Raspberry Pi. Essa consiste nel contare il numero del GPIO proprio come se stessimo leggendo in riga. &lt;br /&gt;
;Notazione BCM&lt;br /&gt;
:La notazione BCM fa riferimento alla numerazione dei registri dello specifico modello di processore che stiamo utilizzando, dato che scrivere su una periferica di I/O dal punto di vista del processore e' come scrivere in un registro.&lt;br /&gt;
&lt;br /&gt;
[[File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png|200px|thumb|center|Mappa con numerazione BCM e BOARD]]&lt;br /&gt;
&lt;br /&gt;
La notazione BCM e' quella che viene usata dal kernel quando vogliamo attivare direttamente il GPIO.&lt;br /&gt;
ad esempio possiamo dare i comandi per attivare il gpio 18 per controllare un relay:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
echo 18 &amp;gt; /sys/class/gpio/export&lt;br /&gt;
echo &amp;quot;out&amp;quot; &amp;gt; /sys/class/gpio/gpio18/direction&lt;br /&gt;
echo 1 &amp;gt; /sys/class/gpio/gpio18/value&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il GPIO numero 18 (in notazione BCM) e' quello che ha il &amp;quot;pallino&amp;quot; numero 12 (notazione BOARD).&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Quale_numero_di_GPIO_usare%3F&amp;diff=1252</id>
		<title>Quale numero di GPIO usare?</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Quale_numero_di_GPIO_usare%3F&amp;diff=1252"/>
		<updated>2015-11-05T09:50:44Z</updated>

		<summary type="html">&lt;p&gt;Aletri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Il problema principale che mi sono posto andando a guardare la gpio map del Raspberry è stato: ho due numeri, quale dei due devo utilizzare?&lt;br /&gt;
&lt;br /&gt;
Esistono due diversi modi per interfacciarsi con i GPIO:&lt;br /&gt;
#Notazione BOARD&lt;br /&gt;
#Notazione BROADCOM (BCM)&lt;br /&gt;
&lt;br /&gt;
;Notazione BOARD&lt;br /&gt;
:La notazione BOARD e' quella piu semplice ed e' quella che (nella maggior parte dei casi) garantisce una maggiore portabilita' tra i vari modelli di Raspberry Pi. Essa consiste nel contare il numero del GPIO proprio come se stessimo leggendo in riga. &lt;br /&gt;
;Notazione BCM&lt;br /&gt;
:La notazione BCM fa riferimento alla numerazione dei registri dello specifico modello di processore che stiamo utilizzando, dato che scrivere su una periferica di I/O dal punto di vista del processore e' come scrivere in un registro.&lt;br /&gt;
&lt;br /&gt;
[[File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png|200px|thumb|center|Mappa con numerazione BCM e BOARD]]&lt;br /&gt;
&lt;br /&gt;
La notazione BCM e' quella che viene usata dal kernel quando vogliamo attivare direttamente il GPIO.&lt;br /&gt;
ad esempio possiamo dare i comandi per attivare il gpio 18 per controllare un relay:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
echo 18 &amp;gt; /sys/class/gpio/export&lt;br /&gt;
echo &amp;quot;out&amp;quot; &amp;gt; /sys/class/gpio/gpio18/direction&lt;br /&gt;
echo 1 &amp;gt; /sys/class/gpio/value&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il GPIO numero 18 (in notazione BCM) e' quello che ha il &amp;quot;pallino&amp;quot; numero 12 (notazione BOARD).&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Quale_numero_di_GPIO_usare%3F&amp;diff=1251</id>
		<title>Quale numero di GPIO usare?</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Quale_numero_di_GPIO_usare%3F&amp;diff=1251"/>
		<updated>2015-11-05T09:29:46Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Created page with &amp;quot;Il problema principale che mi sono posto andando a guardare la gpio map del Raspberry è stato: ho due numeri, quale dei due devo utilizzare?  Esistono due diversi modi per in...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Il problema principale che mi sono posto andando a guardare la gpio map del Raspberry è stato: ho due numeri, quale dei due devo utilizzare?&lt;br /&gt;
&lt;br /&gt;
Esistono due diversi modi per interfacciarsi con i GPIO:&lt;br /&gt;
#Notazione BOARD&lt;br /&gt;
#Notazione BROADCOM (BCM)&lt;br /&gt;
&lt;br /&gt;
;Notazione BOARD&lt;br /&gt;
:La notazione BOARD e' quella piu semplice ed e' quella che (nella maggior parte dei casi) garantisce una maggiore portabilita' tra i vari modelli di Raspberry Pi. Essa consiste nel contare il numero del GPIO proprio come se stessimo leggendo in riga. &lt;br /&gt;
;Notazione BCM&lt;br /&gt;
:La notazione BCM fa riferimento alla numerazione dei registri dello specifico modello di processore che stiamo utilizzando, dato che scrivere su una periferica di I/O dal punto di vista del processore e' come scrivere in un registro.&lt;br /&gt;
&lt;br /&gt;
[[File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png|200px|thumb|center|Mappa con numerazione BCM e BOARD]]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png&amp;diff=1250</id>
		<title>File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png&amp;diff=1250"/>
		<updated>2015-11-05T09:24:37Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Aletri uploaded a new version of &amp;amp;quot;File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png&amp;diff=1249</id>
		<title>File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=File:Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900-1024x341.png&amp;diff=1249"/>
		<updated>2015-11-05T09:21:02Z</updated>

		<summary type="html">&lt;p&gt;Aletri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1248</id>
		<title>Sistemi Operativi:Community portal</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1248"/>
		<updated>2015-11-05T09:02:52Z</updated>

		<summary type="html">&lt;p&gt;Aletri: aggiunta notazione gpio BCM e BOARD&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pensavo di utilizzare questa pagina del community portal per scambiarci suggerimenti per quanto riguarda la parte di elettronica. -- [[User:Aletri|Aletri]] ([[User talk:Aletri|talk]]) 09:58, 5 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
*[[RaspberryPi - Interfacciarsi con un relay, esempio]]&lt;br /&gt;
*[[Quale numero di GPIO usare?]]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1247</id>
		<title>Sistemi Operativi:Community portal</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1247"/>
		<updated>2015-11-05T08:59:06Z</updated>

		<summary type="html">&lt;p&gt;Aletri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pensavo di utilizzare questa pagina del community portal per scambiarci suggerimenti per quanto riguarda la parte di elettronica. &lt;br /&gt;
newline&lt;br /&gt;
[[User:Aletri|Aletri]] ([[User talk:Aletri|talk]]) 09:58, 5 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
*[[RaspberryPi - Interfacciarsi con un relay, esempio]]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1246</id>
		<title>Sistemi Operativi:Community portal</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1246"/>
		<updated>2015-11-05T08:58:06Z</updated>

		<summary type="html">&lt;p&gt;Aletri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pensavo di utilizzare questa pagina del community portal per scambiarci suggerimenti per quanto riguarda la parte di elettronica. &lt;br /&gt;
[[User:Aletri|Aletri]] ([[User talk:Aletri|talk]]) 09:58, 5 November 2015 (CET)&lt;br /&gt;
&lt;br /&gt;
*[[RaspberryPi - Interfacciarsi con un relay, esempio]]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=RaspberryPi_-_Interfacciarsi_con_un_relay,_esempio&amp;diff=1245</id>
		<title>RaspberryPi - Interfacciarsi con un relay, esempio</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=RaspberryPi_-_Interfacciarsi_con_un_relay,_esempio&amp;diff=1245"/>
		<updated>2015-11-04T21:37:01Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Programma per controllare le luci in casa&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Vi posto il programmino in python che ho scritto per controllare un relay. Questo è il programma che uso per accendere e spegnere le luci in camera. Se siete particolarmente pigri come me potreste utilizzarlo come sveglia, o se ci allegate un programmino che controlla l'input di un rilevatore di movimenti potete accendere le luci automaticamente quando entrate in camera. B-) &lt;br /&gt;
Da notare che a quanto pare il relay abbia la logica invertita, per cui dando il segnale LOW in realtà mandiamo 3.3V (accendendo il relay) e dando invece HIGH si torna a 0V.&lt;br /&gt;
Ho appena iniziato a cimentarmi con il python quindi se avete suggerimenti li accetto ben volentieri.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
&lt;br /&gt;
#MagicLamp 1.0&lt;br /&gt;
#questo programma e' usato per controllare un relay. Esegue un controllo di esistenza su due file shut_path e interr_path. &lt;br /&gt;
#Se shut_path e' presente termina il programma; se interr_path è presente accende il relay.&lt;br /&gt;
&lt;br /&gt;
import RPi.GPIO as GPIO&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#numero del pin GPIO&lt;br /&gt;
pin1 = #numero del GPIO che state usando&lt;br /&gt;
#questo file (se presente) viene usato per terminare il programma&lt;br /&gt;
shut_path= '**qui la path dove viene controllata l'esistenza dell'interruttore di terminazione**'  &lt;br /&gt;
#questo file (se presente) viene usato per accendere la luce&lt;br /&gt;
interr_path= '**qui la path dove viene controllata l'esistenza dell'interruttore di accensione e spegnimento**'    &lt;br /&gt;
#questa variabile viene usata per controllare che la luce non sia gia' accesa cosi da non inviare il segnale due volte&lt;br /&gt;
on = False  &lt;br /&gt;
&lt;br /&gt;
GPIO.setmode(GPIO.BOARD)&lt;br /&gt;
GPIO.setup(pin1,GPIO.OUT)   #utilizza il relay numero 1&lt;br /&gt;
#GPIO.output(pin1, GPIO.HIGH)    #spegni la lampada&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
&lt;br /&gt;
#rimuovo shut_path se presente poichè viene usao in fase di terminazione del servizio&lt;br /&gt;
    if (os.path.isfile (interr_path) == True):&lt;br /&gt;
        os.remove(interr_path)&lt;br /&gt;
    if (os.path.isfile (shut_path) == True):&lt;br /&gt;
        os.remove( shut_path)&lt;br /&gt;
    print (&amp;quot;MagicLamp 0.1..... Ready!&amp;quot;)&lt;br /&gt;
    sleep (1)&lt;br /&gt;
    while (1):&lt;br /&gt;
       shutdown  = os.path.isfile (shut_path)&lt;br /&gt;
       interruttore = os.path.isfile (interr_path)&lt;br /&gt;
       if (interruttore == True and shutdown == False):&lt;br /&gt;
            if (on == False):   #se non e gia accesa&lt;br /&gt;
                GPIO.output(pin1, GPIO.LOW) #accendi la lampada&lt;br /&gt;
                print (&amp;quot;Accendo la luce...\n&amp;quot;)&lt;br /&gt;
                on = True&lt;br /&gt;
       elif (shutdown == True):&lt;br /&gt;
            if (on == True):&lt;br /&gt;
                print (&amp;quot;Spengo la luce e termino il programma...\n&amp;quot;)&lt;br /&gt;
#rimuovi i file di controllo per un riavvio pulito&lt;br /&gt;
            os.remove( shut_path)&lt;br /&gt;
            if (interruttore == True):&lt;br /&gt;
                os.remove( interr_path)&lt;br /&gt;
            else:&lt;br /&gt;
                print (&amp;quot;Termino il programma&amp;quot;)&lt;br /&gt;
            break&lt;br /&gt;
       else:&lt;br /&gt;
          if (on == True):&lt;br /&gt;
            GPIO.output(pin1, GPIO.HIGH)    #spegni la luce&lt;br /&gt;
            print (&amp;quot;Spengo la lampada\n&amp;quot;)&lt;br /&gt;
            on = False&lt;br /&gt;
       sleep (5)&lt;br /&gt;
    GPIO.output(pin1, GPIO.HIGH)    #spengo la luce &lt;br /&gt;
    GPIO.cleanup()&lt;br /&gt;
&lt;br /&gt;
except KeyboardInterrupt:&lt;br /&gt;
    GPIO.output(pin1, GPIO.HIGH)&lt;br /&gt;
    GPIO.cleanup()&lt;br /&gt;
    if (os.path.isfile (interr_path) == True):&lt;br /&gt;
        os.remove( interr_path)&lt;br /&gt;
    if (os.path.isfile (shut_path) == True):&lt;br /&gt;
        os.remove( shut_path)&lt;br /&gt;
    print('Termino il programma\n')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
potete poi accendere e spegnere la la luce con uno script fatto così:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
INTERRUTTORE=&amp;quot;**path del vostro interruttore**&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ -e &amp;quot;$INTERRUTTORE&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
rm &amp;quot;$INTERRUTTORE&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
echo 1 &amp;gt; &amp;quot;$INTERRUTTORE&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1244</id>
		<title>Sistemi Operativi:Community portal</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Sistemi_Operativi:Community_portal&amp;diff=1244"/>
		<updated>2015-11-04T21:12:40Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Aggiunta sezione di elettronica&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pensavo di utilizzare questa pagina del community portal per scambiarci suggerimenti per quanto riguarda la parte di elettronica. &lt;br /&gt;
- Aletri&lt;br /&gt;
&lt;br /&gt;
*[[RaspberryPi - Interfacciarsi con un relay, esempio]]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Genesi_del_linguaggio_C:_intenzioni_degli_autori&amp;diff=1166</id>
		<title>Genesi del linguaggio C: intenzioni degli autori</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Genesi_del_linguaggio_C:_intenzioni_degli_autori&amp;diff=1166"/>
		<updated>2015-10-08T08:13:48Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Created page with &amp;quot;''[Questo articolo raccoglie anche alcuni dei punti precedenti]''  Il linguaggio C è definito come un linguaggio imperativo e general purpose. Imperativo poichè composto da ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''[Questo articolo raccoglie anche alcuni dei punti precedenti]''&lt;br /&gt;
&lt;br /&gt;
Il linguaggio C è definito come un linguaggio imperativo e general purpose. Imperativo poichè composto da ''statement'' che cambiano lo ''stato'' di un programma. Il funzionamento di un linguaggio imperativo quindi è molto simile a quello dell'omonimo verbo italiano, ovvero il programmatore impartisce ordini al programma ed esso esegue. &lt;br /&gt;
C è un linguaggio inventato nel 1969 da Dennis Ritchie alla AT&amp;amp;T Bell Labs ed è stato subito adottato in molti ambiti per via della sua plasticità ed efficienza. E' un inguaggio che è stato ridotto all'osso, esso infatti prevede (nelle versioni più moderne) soltanto 32 parole chiave. Tutte le altre funzionionalità (come printf, ecc..) sono implementate a parte nelle librerie che poi potranno essere incluse con delle direttive al preprocessore. L'ottimizzazione del linguaggio C è andata poi ben oltre la semplice ottimizzazione della sintassi e della semantica, si è guardato anche alla produttività del programmatore; Questo ha portato alla scelta di utilizzare come operatore di assegnamento &amp;quot;=&amp;quot; anziché &amp;quot;:=&amp;quot; come si fa ad esempio in Pascal e di utilizzare il simbolo &amp;quot;==&amp;quot; (più complesso) per i confronti, dato che questi ultimi sono statisticamente meno numerosi dei primi.&lt;br /&gt;
&lt;br /&gt;
Un altro punto chiave del C è quello di essere ad ampio spettro. Esso infatti fornisce funzionalità sia alto che di basso livello. Il programmatore ha il pieno controllo della momoria e delle variabili (con tutti i suoi vantaggi e svantaggi).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
References:&lt;br /&gt;
* Wikipedia [https://en.wikipedia.org/wiki/C_%28programming_language%29]&lt;br /&gt;
* Linguaggio imperativo [https://en.wikipedia.org/wiki/Imperative_programming]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Lezioni_Anno_Accademico_2015/16&amp;diff=1165</id>
		<title>Lezioni Anno Accademico 2015/16</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Lezioni_Anno_Accademico_2015/16&amp;diff=1165"/>
		<updated>2015-10-08T07:18:39Z</updated>

		<summary type="html">&lt;p&gt;Aletri: /* temi da trattare: ripasso linguaggio C */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''scrivete qui idee, riassunti dei concetti espressi, commenti approfondimenti sulle lezioni.''&lt;br /&gt;
&lt;br /&gt;
== Lezione del 22 settembre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Introduzione al corso di Sistemi Operativi.&lt;br /&gt;
&lt;br /&gt;
=== concetti ===&lt;br /&gt;
* Hardware vs. Software&lt;br /&gt;
* Informatica&lt;br /&gt;
* Scienza vs. Tecnologia&lt;br /&gt;
* Informazione (vs. Dato)&lt;br /&gt;
* Linguaggio&lt;br /&gt;
* Elaborazione-Memorizzazione-Comunicazione&lt;br /&gt;
* Algoritmo vs. Programma&lt;br /&gt;
* Hacker/Hacking (vs. Cracker)&lt;br /&gt;
* Maker&lt;br /&gt;
* Analogico-Digitale&lt;br /&gt;
&lt;br /&gt;
== Lezione del 23 settembre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Storia dei Sistemi.... anche operativi.&lt;br /&gt;
&lt;br /&gt;
=== concetti ===&lt;br /&gt;
* Architettura a livelli (Layer)&lt;br /&gt;
* SO come livello di astrazione (semplificazione, portabilita')&lt;br /&gt;
* SO come gestore di risorse (controllo, sicurezza, continuita' di servizio)&lt;br /&gt;
* Storia le generazioni: ingranaggi-&amp;gt;Valvole termoioniche-&amp;gt;Transistor-&amp;gt;Circuiti integrati-&amp;gt;Microprocessori&lt;br /&gt;
* I &amp;quot;ruoli&amp;quot; dell'informatica: ideatore, costruttore, programmatore, operatore, utente&lt;br /&gt;
* Multitasking (perche' e' possibile? perche' e quando e' necessario?)&lt;br /&gt;
* Interattivita'&lt;br /&gt;
* TIme sharing&lt;br /&gt;
* Multiuser (multiutente)&lt;br /&gt;
* UNIX&lt;br /&gt;
* Personal Computer (e i sistemi operativi)&lt;br /&gt;
&lt;br /&gt;
== Lezione del 30 settembre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Il materiale per poter replicare l'esperimento sulla portabilit&amp;amp;agrave; dei compilatori &amp;amp;egrave; [http://www.cs.unibo.it/~renzo/so/tools/portability3.tgz qui]. &lt;br /&gt;
&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 09:38, 3 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
Per gli esperimenti con le macchine virtuali:&lt;br /&gt;
* il file debian_wheezy_i386_desktop.qcow2 l'ho preso da qui: https://people.debian.org/~aurel32/qemu/i386/.&lt;br /&gt;
il comando per kvm &amp;amp;egrave;:&lt;br /&gt;
  kvm -m 1G -drive file=$(echo debian_wheezy*.qcow2),cache=writeback -monitor stdio&lt;br /&gt;
* chi volesse provare debian hurd pu&amp;amp;ograve; scaricare l'immagine: debian-hurd-20150424.img da qui: https://www.debian.org/ports/hurd/hurd-install. Nella pagina &amp;amp;egrave; anche indicato come lanciare kvm (io aggiungerei -monitor stdio in fondo per avere la console di qemu-kvm).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 09:47, 3 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
=== concetti ===&lt;br /&gt;
* Conoscenze a breve, medio e lungo termine dell'informatica&lt;br /&gt;
* Linguaggio dell'Hardware&lt;br /&gt;
* X ''Virtuale'' (dove X rappresenta qualsiasi cosa)&lt;br /&gt;
* Emulazione/Simulazione&lt;br /&gt;
* virtualizzazione senza emulazione&lt;br /&gt;
* Cosa e', cosa non e' e dov'e' (realmente) il sistema operativo&lt;br /&gt;
* macchine virtuali&lt;br /&gt;
* Distribuzione e Ambiente Operativo&lt;br /&gt;
* Licenze: differenza fra Software Libero e Open Source&lt;br /&gt;
&lt;br /&gt;
== Lezione del 07 ottobre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Ricordo che &amp;amp;egrave; in sospeso una domanda: [[&amp;quot;l'arduino ha un sistema operativo?&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
=== temi da trattare: ripasso linguaggio C ===&lt;br /&gt;
* Compilatori vs. Interpreti&lt;br /&gt;
* Programmi vs. Script&lt;br /&gt;
* Le classi di linguaggi di programmazione&lt;br /&gt;
* Il &amp;quot;livello&amp;quot; dei linguaggi di programmazione&lt;br /&gt;
* Cosa e', cosa non e' il Linguaggio C&lt;br /&gt;
* [[Genesi del linguaggio C: intenzioni degli autori]]&lt;br /&gt;
* Le '''vere''' novita' del linguaggio C&lt;br /&gt;
&lt;br /&gt;
=== temi da trattare: ripasso architettura ===&lt;br /&gt;
* Modelli architetturali: von Neumann vs. Harvard&lt;br /&gt;
* Struttura del processore: Control Path, Data Path&lt;br /&gt;
* CISC vs RISC&lt;br /&gt;
* Bus Indirizzi, Bus Dati, Gerarchie di Bus&lt;br /&gt;
* Interrupt (e Trap)&lt;br /&gt;
* Mascheramento degli Interrupt&lt;br /&gt;
* Gestione nidificata degli interrupt&lt;br /&gt;
* DMA (Direct Memory Access)&lt;br /&gt;
* Gerarchia di Memeoria&lt;br /&gt;
* Cache&lt;br /&gt;
* Indirizzi Logici, Indirizzi Fisici&lt;br /&gt;
* Rilocazione&lt;br /&gt;
&lt;br /&gt;
== Lezione del 14 ottobre 2015 ==&lt;br /&gt;
&lt;br /&gt;
== Lezione del 21 ottobre 2015 ==&lt;br /&gt;
&lt;br /&gt;
== Lezione del 28 ottobre 2015 ==&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=%22l%27arduino_ha_un_sistema_operativo%3F%22&amp;diff=1164</id>
		<title>&quot;l'arduino ha un sistema operativo?&quot;</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=%22l%27arduino_ha_un_sistema_operativo%3F%22&amp;diff=1164"/>
		<updated>2015-10-08T07:02:44Z</updated>

		<summary type="html">&lt;p&gt;Aletri: Created page with &amp;quot;I programmi di Arduino vengono caricati tramite un programma chiamato [Sketch : http://arduino.cc/en/Main/Software]. Il programma caricato viene preso in gestione da un bootst...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I programmi di Arduino vengono caricati tramite un programma chiamato [Sketch : http://arduino.cc/en/Main/Software]. Il programma caricato viene preso in gestione da un bootstrapper che però, a differenza degli altri sistemi comuni, rimane in esecuzione per tutto il tempo. Infatti i programmi per Arduino non hanno main, ma hanno una funzione di loop che viene chiamata ripetutamente dal bootstrapper.&lt;br /&gt;
Dalla definizione di Sistema Operativo ricordiamo che:&lt;br /&gt;
un sistema operativo è un programma che viene avviato al momento del boot e rimane in esecuzione per tutto il tempo.&lt;br /&gt;
&lt;br /&gt;
Notiamo quindi che nel caso dell'Arduino il bootstrapper potrebbe essere considerato una sorta di sistema operativo, sebbene i programmi abbiano accesso diretto all'hardware.&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Lezioni_Anno_Accademico_2015/16&amp;diff=1163</id>
		<title>Lezioni Anno Accademico 2015/16</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Lezioni_Anno_Accademico_2015/16&amp;diff=1163"/>
		<updated>2015-10-08T06:29:04Z</updated>

		<summary type="html">&lt;p&gt;Aletri: /* Lezione del 07 ottobre 2015 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''scrivete qui idee, riassunti dei concetti espressi, commenti approfondimenti sulle lezioni.''&lt;br /&gt;
&lt;br /&gt;
== Lezione del 22 settembre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Introduzione al corso di Sistemi Operativi.&lt;br /&gt;
&lt;br /&gt;
=== concetti ===&lt;br /&gt;
* Hardware vs. Software&lt;br /&gt;
* Informatica&lt;br /&gt;
* Scienza vs. Tecnologia&lt;br /&gt;
* Informazione (vs. Dato)&lt;br /&gt;
* Linguaggio&lt;br /&gt;
* Elaborazione-Memorizzazione-Comunicazione&lt;br /&gt;
* Algoritmo vs. Programma&lt;br /&gt;
* Hacker/Hacking (vs. Cracker)&lt;br /&gt;
* Maker&lt;br /&gt;
* Analogico-Digitale&lt;br /&gt;
&lt;br /&gt;
== Lezione del 23 settembre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Storia dei Sistemi.... anche operativi.&lt;br /&gt;
&lt;br /&gt;
=== concetti ===&lt;br /&gt;
* Architettura a livelli (Layer)&lt;br /&gt;
* SO come livello di astrazione (semplificazione, portabilita')&lt;br /&gt;
* SO come gestore di risorse (controllo, sicurezza, continuita' di servizio)&lt;br /&gt;
* Storia le generazioni: ingranaggi-&amp;gt;Valvole termoioniche-&amp;gt;Transistor-&amp;gt;Circuiti integrati-&amp;gt;Microprocessori&lt;br /&gt;
* I &amp;quot;ruoli&amp;quot; dell'informatica: ideatore, costruttore, programmatore, operatore, utente&lt;br /&gt;
* Multitasking (perche' e' possibile? perche' e quando e' necessario?)&lt;br /&gt;
* Interattivita'&lt;br /&gt;
* TIme sharing&lt;br /&gt;
* Multiuser (multiutente)&lt;br /&gt;
* UNIX&lt;br /&gt;
* Personal Computer (e i sistemi operativi)&lt;br /&gt;
&lt;br /&gt;
== Lezione del 30 settembre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Il materiale per poter replicare l'esperimento sulla portabilit&amp;amp;agrave; dei compilatori &amp;amp;egrave; [http://www.cs.unibo.it/~renzo/so/tools/portability3.tgz qui]. &lt;br /&gt;
&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 09:38, 3 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
Per gli esperimenti con le macchine virtuali:&lt;br /&gt;
* il file debian_wheezy_i386_desktop.qcow2 l'ho preso da qui: https://people.debian.org/~aurel32/qemu/i386/.&lt;br /&gt;
il comando per kvm &amp;amp;egrave;:&lt;br /&gt;
  kvm -m 1G -drive file=$(echo debian_wheezy*.qcow2),cache=writeback -monitor stdio&lt;br /&gt;
* chi volesse provare debian hurd pu&amp;amp;ograve; scaricare l'immagine: debian-hurd-20150424.img da qui: https://www.debian.org/ports/hurd/hurd-install. Nella pagina &amp;amp;egrave; anche indicato come lanciare kvm (io aggiungerei -monitor stdio in fondo per avere la console di qemu-kvm).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 09:47, 3 October 2015 (CEST)&lt;br /&gt;
&lt;br /&gt;
=== concetti ===&lt;br /&gt;
* Conoscenze a breve, medio e lungo termine dell'informatica&lt;br /&gt;
* Linguaggio dell'Hardware&lt;br /&gt;
* X ''Virtuale'' (dove X rappresenta qualsiasi cosa)&lt;br /&gt;
* Emulazione/Simulazione&lt;br /&gt;
* virtualizzazione senza emulazione&lt;br /&gt;
* Cosa e', cosa non e' e dov'e' (realmente) il sistema operativo&lt;br /&gt;
* macchine virtuali&lt;br /&gt;
* Distribuzione e Ambiente Operativo&lt;br /&gt;
* Licenze: differenza fra Software Libero e Open Source&lt;br /&gt;
&lt;br /&gt;
== Lezione del 07 ottobre 2015 ==&lt;br /&gt;
&lt;br /&gt;
Ricordo che &amp;amp;egrave; in sospeso una domanda: [[&amp;quot;l'arduino ha un sistema operativo?&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
=== temi da trattare: ripasso linguaggio C ===&lt;br /&gt;
* Compilatori vs. Interpreti&lt;br /&gt;
* Programmi vs. Script&lt;br /&gt;
* Le classi di linguaggi di programmazione&lt;br /&gt;
* Il &amp;quot;livello&amp;quot; dei linguaggi di programmazione&lt;br /&gt;
* Cosa e', cosa non e' il Linguaggio C&lt;br /&gt;
* Genesi del linguaggio C: intenzioni degli autori&lt;br /&gt;
* Le '''vere''' novita' del linguaggio C&lt;br /&gt;
&lt;br /&gt;
=== temi da trattare: ripasso architettura ===&lt;br /&gt;
* Modelli architetturali: von Neumann vs. Harvard&lt;br /&gt;
* Struttura del processore: Control Path, Data Path&lt;br /&gt;
* CISC vs RISC&lt;br /&gt;
* Bus Indirizzi, Bus Dati, Gerarchie di Bus&lt;br /&gt;
* Interrupt (e Trap)&lt;br /&gt;
* Mascheramento degli Interrupt&lt;br /&gt;
* Gestione nidificata degli interrupt&lt;br /&gt;
* DMA (Direct Memory Access)&lt;br /&gt;
* Gerarchia di Memeoria&lt;br /&gt;
* Cache&lt;br /&gt;
* Indirizzi Logici, Indirizzi Fisici&lt;br /&gt;
* Rilocazione&lt;br /&gt;
&lt;br /&gt;
== Lezione del 14 ottobre 2015 ==&lt;br /&gt;
&lt;br /&gt;
== Lezione del 21 ottobre 2015 ==&lt;br /&gt;
&lt;br /&gt;
== Lezione del 28 ottobre 2015 ==&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Main_Page&amp;diff=1145</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Main_Page&amp;diff=1145"/>
		<updated>2015-10-01T07:18:29Z</updated>

		<summary type="html">&lt;p&gt;Aletri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Questo &amp;amp;egrave; il Wiki del Corso di Sistemi Operativi&lt;br /&gt;
&lt;br /&gt;
[[Materiale dell'AA 2015-16]]&lt;br /&gt;
&lt;br /&gt;
[[Materiale dell'AA 2014-15]]&lt;br /&gt;
&lt;br /&gt;
[[Materiale dell'AA 2013-14]]&lt;br /&gt;
----&lt;br /&gt;
Ricordate che per creare un account o quando viene richiesto di risolvere un semplice calcolo occorre ricordare quanto scritto [[qui]]&lt;/div&gt;</summary>
		<author><name>Aletri</name></author>
	</entry>
</feed>