<?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=MV</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=MV"/>
	<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php/Special:Contributions/MV"/>
	<updated>2026-05-02T13:26:27Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.5</generator>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_18-06-2015&amp;diff=1141</id>
		<title>Prova Pratica 18-06-2015</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_18-06-2015&amp;diff=1141"/>
		<updated>2015-06-30T10:20:15Z</updated>

		<summary type="html">&lt;p&gt;MV: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Usando signalfd (e non signal o sigaction) scrivere due programmi tx e rx.&lt;br /&gt;
Rx deve essere attivato per primo e per prima cosa stampa il suo pid e aspetta.&lt;br /&gt;
Tx ha due parametri: il pid del ricevente rx e una stringa.&lt;br /&gt;
Rx deve stampare la stringa passata come secondo parametro e uscire. La stringa deve essere spedita usando solo segnali.&lt;br /&gt;
Ogni bit di ogni carattere deve essere inviato usando SIGUSR1 se vale 1 e SIGUSR2 se vale 0.&lt;br /&gt;
Al ricevimento di ogni bit rx spedisce un segnale di acknowledgement a tx che provvede a spedire il successivo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Esercizio1: Tx&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&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;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define EXIT_WITH_ERROR(function) \&lt;br /&gt;
	{ \&lt;br /&gt;
		printf(&amp;quot;Error %i in &amp;quot;,errno); \&lt;br /&gt;
		printf(function); \&lt;br /&gt;
		printf(&amp;quot;: %s\n&amp;quot;,strerror(errno)); \&lt;br /&gt;
		exit(EXIT_FAILURE); \&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
	pid_t rx;&lt;br /&gt;
	char *str;&lt;br /&gt;
	sigset_t mask;&lt;br /&gt;
	int sfd;&lt;br /&gt;
	struct signalfd_siginfo siginfo;&lt;br /&gt;
	&lt;br /&gt;
	if(argc != 3)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Usage: Tx rx string\n&amp;quot;);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if(sscanf(argv[1],&amp;quot;%i&amp;quot;,&amp;amp;rx) != 1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sscanf&amp;quot;);&lt;br /&gt;
	str = argv[2];&lt;br /&gt;
	&lt;br /&gt;
	// setto il sigset_t a contenere SIGUSR1 (sara' l'acknowledgement)&lt;br /&gt;
	sigemptyset(&amp;amp;mask);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
	&lt;br /&gt;
	// annullo l'azione standard per SIGUSR1&lt;br /&gt;
	if (sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL) == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sigprocmask&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	sfd = signalfd(-1, &amp;amp;mask, 0);&lt;br /&gt;
	if (sfd == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;signalfd&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		int i;&lt;br /&gt;
		char c = *str;&lt;br /&gt;
		&lt;br /&gt;
		// invia i bit del carattere (dal piu' al meno significativo)&lt;br /&gt;
		for(i=7; i&amp;gt;=0; i--)&lt;br /&gt;
		{&lt;br /&gt;
			if((c&amp;gt;&amp;gt;i)&amp;amp;1)	// prendo l'i-esimo bit di c:&lt;br /&gt;
			{				// SIGUSR1 se e' 1&lt;br /&gt;
				if(kill(rx,SIGUSR1) == -1)&lt;br /&gt;
					EXIT_WITH_ERROR(&amp;quot;kill&amp;quot;)&lt;br /&gt;
			}&lt;br /&gt;
			else 			// SIGUSR2 se invece e' 0&lt;br /&gt;
			{&lt;br /&gt;
				if(kill(rx,SIGUSR2) == -1)&lt;br /&gt;
					EXIT_WITH_ERROR(&amp;quot;kill&amp;quot;)&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// attendo SIGUSR1 da Rx&lt;br /&gt;
			int len = read(sfd, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
			if(len != sizeof(struct signalfd_siginfo))&lt;br /&gt;
				EXIT_WITH_ERROR(&amp;quot;read&amp;quot;)&lt;br /&gt;
		}&lt;br /&gt;
		if(c == 0)	// esce se ha appena inviato fine-stringa&lt;br /&gt;
			break;&lt;br /&gt;
		str++;&lt;br /&gt;
	}&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Esercizio1: Rx&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&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;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define EXIT_WITH_ERROR(function) \&lt;br /&gt;
	{ \&lt;br /&gt;
		printf(&amp;quot;Error %i in &amp;quot;,errno); \&lt;br /&gt;
		printf(function); \&lt;br /&gt;
		printf(&amp;quot;: %s\n&amp;quot;,strerror(errno)); \&lt;br /&gt;
		exit(EXIT_FAILURE); \&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
	pid_t mypid;&lt;br /&gt;
	sigset_t mask;&lt;br /&gt;
	int sfd;&lt;br /&gt;
	struct signalfd_siginfo siginfo;&lt;br /&gt;
	char c;&lt;br /&gt;
	&lt;br /&gt;
	mypid = getpid();&lt;br /&gt;
	printf(&amp;quot;%i\n&amp;quot;,mypid);&lt;br /&gt;
	&lt;br /&gt;
	// setto il sigset_t&lt;br /&gt;
	sigemptyset(&amp;amp;mask);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR2);&lt;br /&gt;
	&lt;br /&gt;
	// annullo l'azione standard per SIGUSR1 e SIGUSR2&lt;br /&gt;
	if (sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL) == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sigprocmask&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	sfd = signalfd(-1, &amp;amp;mask, 0);&lt;br /&gt;
	if (sfd == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;signalfd&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	do&lt;br /&gt;
	{&lt;br /&gt;
		int i;&lt;br /&gt;
		c = 0;&lt;br /&gt;
		&lt;br /&gt;
		// riceve 8 segnali per ogni carattere &lt;br /&gt;
		for(i=7; i&amp;gt;=0; i--)&lt;br /&gt;
		{&lt;br /&gt;
			int len = read(sfd, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
			if(len != sizeof(struct signalfd_siginfo))&lt;br /&gt;
				EXIT_WITH_ERROR(&amp;quot;read&amp;quot;)&lt;br /&gt;
			&lt;br /&gt;
			if (siginfo.ssi_signo == SIGUSR1)	// se ho ricevuto SIGUSR1&lt;br /&gt;
				c = c | (1 &amp;lt;&amp;lt; i);	// setto il bit a 1&lt;br /&gt;
			// altrimenti e' sicuramente SIGUSR2 =&amp;gt; il bit resta 0&lt;br /&gt;
			&lt;br /&gt;
			kill(siginfo.ssi_pid, SIGUSR1);	// invio l'acknowledgement al mittente del segnale&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;%c&amp;quot;,c);&lt;br /&gt;
	} while(c != 0);	// se tutti i bit a 0 =&amp;gt; fine stringa&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;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Esercizio2==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Si costruiscano due programmi txtime e rxnull per stimare l'efficienza di tx e rx.&lt;br /&gt;
Rxnull e' uguale all'rx precedente ma non stampa nulla.&lt;br /&gt;
Txtime ha come parametri il pid del ricevente e un numero intero n. Txtime deve spedire n caratteri 'K' al txtnull e alla fine deve stampare&lt;br /&gt;
il tempo medio impiegato per spedire un carattere.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Esercizio2: txtime&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&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;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;sys/timeb.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define EXIT_WITH_ERROR(function) \&lt;br /&gt;
	{ \&lt;br /&gt;
		printf(&amp;quot;Error %i in &amp;quot;,errno); \&lt;br /&gt;
		printf(function); \&lt;br /&gt;
		printf(&amp;quot;: %s\n&amp;quot;,strerror(errno)); \&lt;br /&gt;
		exit(EXIT_FAILURE); \&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
	pid_t rx;&lt;br /&gt;
	int n;&lt;br /&gt;
	int j;&lt;br /&gt;
	&lt;br /&gt;
	// variabili per calcolare il tempo medio di trasmissione&lt;br /&gt;
	struct timeb time_start, time_end;&lt;br /&gt;
	int millisec;&lt;br /&gt;
	float media;&lt;br /&gt;
	&lt;br /&gt;
	sigset_t mask;&lt;br /&gt;
	int sfd;&lt;br /&gt;
	struct signalfd_siginfo siginfo;&lt;br /&gt;
	&lt;br /&gt;
	if(argc != 3)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Usage: Tx rx string\n&amp;quot;);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if(sscanf(argv[1],&amp;quot;%i&amp;quot;,&amp;amp;rx) != 1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sscanf&amp;quot;);&lt;br /&gt;
	if(sscanf(argv[2],&amp;quot;%i&amp;quot;,&amp;amp;n) != 1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sscanf&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	ftime(&amp;amp;time_start);&lt;br /&gt;
	&lt;br /&gt;
	// setto il sigset_t a contenere SIGUSR1 (sara' l'acknowledgement)&lt;br /&gt;
	sigemptyset(&amp;amp;mask);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
	&lt;br /&gt;
	// annullo l'azione standard per SIGUSR1&lt;br /&gt;
	if (sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL) == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sigprocmask&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	sfd = signalfd(-1, &amp;amp;mask, 0);&lt;br /&gt;
	if (sfd == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;signalfd&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// invio n caratteri 'K' &lt;br /&gt;
	for(j=0; j&amp;lt;n; j++)&lt;br /&gt;
	{&lt;br /&gt;
		int i;&lt;br /&gt;
		char c = 'K';&lt;br /&gt;
		&lt;br /&gt;
		for(i=7; i&amp;gt;=0; i--)&lt;br /&gt;
		{&lt;br /&gt;
			if((c&amp;gt;&amp;gt;i)&amp;amp;1)	// prendo l'i-esimo bit di c:&lt;br /&gt;
			{				// SIGUSR1 se e' 1&lt;br /&gt;
				if(kill(rx,SIGUSR1) == -1)&lt;br /&gt;
					EXIT_WITH_ERROR(&amp;quot;kill&amp;quot;)&lt;br /&gt;
			}&lt;br /&gt;
			else 			// SIGUSR2 se invece e' 0&lt;br /&gt;
			{&lt;br /&gt;
				if(kill(rx,SIGUSR2) == -1)&lt;br /&gt;
					EXIT_WITH_ERROR(&amp;quot;kill&amp;quot;)&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// sospendo il processo in attesa div SIGUSR1&lt;br /&gt;
			int len = read(sfd, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
			if(len != sizeof(struct signalfd_siginfo))&lt;br /&gt;
				EXIT_WITH_ERROR(&amp;quot;read&amp;quot;)&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	ftime(&amp;amp;time_end);&lt;br /&gt;
	&lt;br /&gt;
	// calcolo il tempo medio di trasmissione&lt;br /&gt;
	millisec = (time_end.time - time_start.time)*1000 + (time_end.millitm - time_start.millitm);&lt;br /&gt;
	media = (float)(millisec)/n;&lt;br /&gt;
	printf(&amp;quot;Tempo medio: %f ms per carattere.\n&amp;quot;,media);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Esercizio2: rxnull&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&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;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define EXIT_WITH_ERROR(function) \&lt;br /&gt;
	{ \&lt;br /&gt;
		printf(&amp;quot;Error %i in &amp;quot;,errno); \&lt;br /&gt;
		printf(function); \&lt;br /&gt;
		printf(&amp;quot;: %s\n&amp;quot;,strerror(errno)); \&lt;br /&gt;
		exit(EXIT_FAILURE); \&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
	pid_t mypid;&lt;br /&gt;
	sigset_t mask;&lt;br /&gt;
	int sfd;&lt;br /&gt;
	struct signalfd_siginfo siginfo;&lt;br /&gt;
	char c;&lt;br /&gt;
	&lt;br /&gt;
	mypid = getpid();&lt;br /&gt;
	printf(&amp;quot;%i\n&amp;quot;,mypid);&lt;br /&gt;
	&lt;br /&gt;
	// setto il sigset_t&lt;br /&gt;
	sigemptyset(&amp;amp;mask);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR2);&lt;br /&gt;
	&lt;br /&gt;
	// annullo l'azione standard per SIGUSR1 e SIGUSR2&lt;br /&gt;
	if (sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL) == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sigprocmask&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	sfd = signalfd(-1, &amp;amp;mask, 0);&lt;br /&gt;
	if (sfd == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;signalfd&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	do&lt;br /&gt;
	{&lt;br /&gt;
		int i;&lt;br /&gt;
		c = 0;&lt;br /&gt;
		&lt;br /&gt;
		for(i=7; i&amp;gt;=0; i--)&lt;br /&gt;
		{&lt;br /&gt;
			int len = read(sfd, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
			if(len != sizeof(struct signalfd_siginfo))&lt;br /&gt;
				EXIT_WITH_ERROR(&amp;quot;read&amp;quot;)&lt;br /&gt;
			&lt;br /&gt;
			if (siginfo.ssi_signo == SIGUSR1)	// se ho ricevuto SIGUSR1&lt;br /&gt;
				c = c | (1 &amp;lt;&amp;lt; i);	// setto il bit a 1&lt;br /&gt;
			// altrimenti e' sicuramente SIGUSR2 =&amp;gt; il bit resta 0&lt;br /&gt;
			&lt;br /&gt;
			kill(siginfo.ssi_pid, SIGUSR1);	// invio l'acknowledgement al mittente del segnale&lt;br /&gt;
		}&lt;br /&gt;
	} while(c != 0);	// se tutti i bit a 0 =&amp;gt; fine stringa&lt;br /&gt;
	// NOTA: questo programma non termina normalmente se usato con txtime&lt;br /&gt;
	&lt;br /&gt;
	printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_18-06-2015&amp;diff=1140</id>
		<title>Prova Pratica 18-06-2015</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_18-06-2015&amp;diff=1140"/>
		<updated>2015-06-30T10:13:55Z</updated>

		<summary type="html">&lt;p&gt;MV: Created page with &amp;quot;==Esercizio1== &amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt; Usando signalfd (e non signal o sigaction) scrivere due programmi tx e rx. Rx deve essere attivato per primo e per prima cosa stampa il suo...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Usando signalfd (e non signal o sigaction) scrivere due programmi tx e rx.&lt;br /&gt;
Rx deve essere attivato per primo e per prima cosa stampa il suo pid e aspetta.&lt;br /&gt;
Tx ha due parametri: il pid del ricevente rx e una stringa.&lt;br /&gt;
Rx deve stampare la stringa passata come secondo parametro e uscire. La stringa deve essere spedita usando solo segnali.&lt;br /&gt;
Ogni bit di ogni carattere deve essere inviato usando SIGUSR1 se vale 1 e SIGUSR2 se vale 0.&lt;br /&gt;
Al ricevimento di ogni bit rx spedisce un segnale di acknowledgement a tx che provvede a spedire il successivo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Esercizio1: Tx&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&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;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define EXIT_WITH_ERROR(function) \&lt;br /&gt;
	{ \&lt;br /&gt;
		printf(&amp;quot;Error %i in &amp;quot;,errno); \&lt;br /&gt;
		printf(function); \&lt;br /&gt;
		printf(&amp;quot;: %s\n&amp;quot;,strerror(errno)); \&lt;br /&gt;
		exit(EXIT_FAILURE); \&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
	pid_t rx;&lt;br /&gt;
	char *str;&lt;br /&gt;
	sigset_t mask;&lt;br /&gt;
	int sfd;&lt;br /&gt;
	struct signalfd_siginfo siginfo;&lt;br /&gt;
	&lt;br /&gt;
	if(argc != 3)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Usage: Tx rx string\n&amp;quot;);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if(sscanf(argv[1],&amp;quot;%i&amp;quot;,&amp;amp;rx) != 1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sscanf&amp;quot;);&lt;br /&gt;
	str = argv[2];&lt;br /&gt;
	&lt;br /&gt;
	// setto il sigset_t a contenere SIGUSR1 (sara' l'acknowledgement)&lt;br /&gt;
	sigemptyset(&amp;amp;mask);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
	&lt;br /&gt;
	// annullo l'azione standard per SIGUSR1&lt;br /&gt;
	if (sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL) == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sigprocmask&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	sfd = signalfd(-1, &amp;amp;mask, 0);&lt;br /&gt;
	if (sfd == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;signalfd&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		int i;&lt;br /&gt;
		char c = *str;&lt;br /&gt;
		&lt;br /&gt;
		// invia i bit del carattere (dal piu' al meno significativo)&lt;br /&gt;
		for(i=7; i&amp;gt;=0; i--)&lt;br /&gt;
		{&lt;br /&gt;
			if((c&amp;gt;&amp;gt;i)&amp;amp;1)	// prendo l'i-esimo bit di c:&lt;br /&gt;
			{				// SIGUSR1 se e' 1&lt;br /&gt;
				if(kill(rx,SIGUSR1) == -1)&lt;br /&gt;
					EXIT_WITH_ERROR(&amp;quot;kill&amp;quot;)&lt;br /&gt;
			}&lt;br /&gt;
			else 			// SIGUSR2 se invece e' 0&lt;br /&gt;
			{&lt;br /&gt;
				if(kill(rx,SIGUSR2) == -1)&lt;br /&gt;
					EXIT_WITH_ERROR(&amp;quot;kill&amp;quot;)&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// attendo SIGUSR1 da Rx&lt;br /&gt;
			int len = read(sfd, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
			if(len != sizeof(struct signalfd_siginfo))&lt;br /&gt;
				EXIT_WITH_ERROR(&amp;quot;read&amp;quot;)&lt;br /&gt;
		}&lt;br /&gt;
		if(c == 0)	// esce se ha appena inviato fine-stringa&lt;br /&gt;
			break;&lt;br /&gt;
		str++;&lt;br /&gt;
	}&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Esercizio1: Rx&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&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;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define EXIT_WITH_ERROR(function) \&lt;br /&gt;
	{ \&lt;br /&gt;
		printf(&amp;quot;Error %i in &amp;quot;,errno); \&lt;br /&gt;
		printf(function); \&lt;br /&gt;
		printf(&amp;quot;: %s\n&amp;quot;,strerror(errno)); \&lt;br /&gt;
		exit(EXIT_FAILURE); \&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
	pid_t mypid;&lt;br /&gt;
	sigset_t mask;&lt;br /&gt;
	int sfd;&lt;br /&gt;
	struct signalfd_siginfo siginfo;&lt;br /&gt;
	char c;&lt;br /&gt;
	&lt;br /&gt;
	mypid = getpid();&lt;br /&gt;
	printf(&amp;quot;%i\n&amp;quot;,mypid);&lt;br /&gt;
	&lt;br /&gt;
	// setto il sigset_t&lt;br /&gt;
	sigemptyset(&amp;amp;mask);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
	sigaddset(&amp;amp;mask, SIGUSR2);&lt;br /&gt;
	&lt;br /&gt;
	// annullo l'azione standard per SIGUSR1 e SIGUSR2&lt;br /&gt;
	if (sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL) == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;sigprocmask&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	sfd = signalfd(-1, &amp;amp;mask, 0);&lt;br /&gt;
	if (sfd == -1)&lt;br /&gt;
		EXIT_WITH_ERROR(&amp;quot;signalfd&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	do&lt;br /&gt;
	{&lt;br /&gt;
		int i;&lt;br /&gt;
		c = 0;&lt;br /&gt;
		&lt;br /&gt;
		// riceve 8 segnali per ogni carattere &lt;br /&gt;
		for(i=7; i&amp;gt;=0; i--)&lt;br /&gt;
		{&lt;br /&gt;
			int len = read(sfd, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
			if(len != sizeof(struct signalfd_siginfo))&lt;br /&gt;
				EXIT_WITH_ERROR(&amp;quot;read&amp;quot;)&lt;br /&gt;
			&lt;br /&gt;
			if (siginfo.ssi_signo == SIGUSR1)	// se ho ricevuto SIGUSR1&lt;br /&gt;
				c = c | (1 &amp;lt;&amp;lt; i);	// setto il bit a 1&lt;br /&gt;
			// altrimenti e' sicuramente SIGUSR2 =&amp;gt; il bit resta 0&lt;br /&gt;
			&lt;br /&gt;
			kill(siginfo.ssi_pid, SIGUSR1);	// invio l'acknowledgement al mittente del segnale&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;%c&amp;quot;,c);&lt;br /&gt;
	} while(c != 0);	// se tutti i bit a 0 =&amp;gt; fine stringa&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;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_16-07-2014&amp;diff=1127</id>
		<title>Prova Teorica 16-07-2014</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_16-07-2014&amp;diff=1127"/>
		<updated>2015-05-26T20:33:32Z</updated>

		<summary type="html">&lt;p&gt;MV: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
scrivere il monitor mMbb che realizzi un meccanismo di un minmax bounded buffer.&lt;br /&gt;
Dopo le prime MIN operazioni di scrittura, un minmax bounded buffer deve sempre avere almeno MIN elementi e mai piu' di MAX&lt;br /&gt;
elementi (e' quindi limitato sia nell'ampiezza massima, sia nell'ampiezza minima).&lt;br /&gt;
Le funzioni (procedure entry) read e write del minmax bounded buffer hanno gli stessi argomenti e valori di ritorno di quelle del producer/consumer o del bounded buffer ordinario.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Soluzione di Stefano Zaniboni===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/*esercizio 1*/&lt;br /&gt;
&lt;br /&gt;
monitor mMbb{&lt;br /&gt;
	object[] buffer; //spazio di memorizzazione&lt;br /&gt;
	&lt;br /&gt;
	final int MAXELEM; // numero massimo di elementi che ci possono essere nel buffer&lt;br /&gt;
	final int MINELEM; //numero minimo di elementi --&amp;gt; numero di scritture minime&lt;br /&gt;
	&lt;br /&gt;
	condition okW; // dove mi fermo se non posso scrivere&lt;br /&gt;
	condition okR; // dove mi fermo se non posso leggere&lt;br /&gt;
&lt;br /&gt;
	int count; // elementi presenti nel buffer&lt;br /&gt;
	int front;   // contatore al elemento prodotto&lt;br /&gt;
	int rear;   // contatore al elemento consumato	&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
	mMbb(){&lt;br /&gt;
		 buffer = new Object[MAXELEM];&lt;br /&gt;
    	count = rear = front = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	procedure entry object read(){&lt;br /&gt;
		if ((count &amp;lt; MINELEM))  //se il buffer e' pieno oppure non ci sono min elem chiamo la wait&lt;br /&gt;
    		     okR.wait();&lt;br /&gt;
  		eltype val = buffer[rear]; // assegno al val l'elemento che ho letto e poi aggiorno rear&lt;br /&gt;
		rear = ((rear + 1) % (MAXELEM -1 ));  // aggiorno rear;&lt;br /&gt;
		count--; // decremento count per dire che ho consumato un elemento&lt;br /&gt;
  		okW.signal(); // qui faccio signal sui produttori che adesso possono scrivere&lt;br /&gt;
  		return retval;&lt;br /&gt;
	}&lt;br /&gt;
	procedure entry void write(int val){&lt;br /&gt;
		if (count == buffer.length) //se il buffer e' pieno mi fermo&lt;br /&gt;
    		      okW.wait();&lt;br /&gt;
  		buffer[front] = val; //scrivo elemento&lt;br /&gt;
  		count++; //aggiorno i prodotti disponibili&lt;br /&gt;
  		front = ((front+1)%(MAXELEM - 1)); // aggiorno il contatore front a puntare nella prossima posizione&lt;br /&gt;
&lt;br /&gt;
  		okR.signal();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio c.2==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 Facendo uso di semafori scrivere la funzione rendezvous che consenta ai processi di sincronizzarsi secondo le seguenti specifiche:&lt;br /&gt;
– Ogni processo indica come parametro della funzione rendezvous con quanti altri processi vuole sincronizzarsi.&lt;br /&gt;
– M processi che chiamano la rendezvous con parametro N rimangono bloccati se M&amp;lt;N.&lt;br /&gt;
– Quando l'N-mo processo richiama la rendezvous specificando N come parametro, lui e gli N-1 sospesi devono proseguire nelle propria esecuzione&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------- SOLUZIONE DI MV -------------------------&lt;br /&gt;
&lt;br /&gt;
void rendezvous(int N)&lt;br /&gt;
{&lt;br /&gt;
	struct S { Semaphore sem; int N; int M };&lt;br /&gt;
	&lt;br /&gt;
	static List&amp;lt;struct S&amp;gt; L = new List&amp;lt;struct S&amp;gt;();&lt;br /&gt;
	static Semaphore mutex = new Semaphore(1);&lt;br /&gt;
	&lt;br /&gt;
	if(N &amp;lt;= 1)	// se N==1 significa che non vuole sincronizzarsi&lt;br /&gt;
		return;	// se N&amp;lt;1 non ha senso =&amp;gt; esce dalla funzione&lt;br /&gt;
	&lt;br /&gt;
	bool trovato = false;&lt;br /&gt;
	mutex.P();	// prende la mutua esclusione per evitare incoerenze&lt;br /&gt;
	// scorre la lista in cerca di un semaforo per N&lt;br /&gt;
	for(List&amp;lt;struct S&amp;gt; el = L.head(); !L.last(el) &amp;amp;&amp;amp; !trovato; el = L.next(el) )&lt;br /&gt;
		if(el.content.N == N)	// se esiste&lt;br /&gt;
		{&lt;br /&gt;
			trovato = true;&lt;br /&gt;
			if(el.content.M == N-1)	// se è l'N-esimo processo&lt;br /&gt;
			{&lt;br /&gt;
				while(el.content.M)	// sblocca tutti gli altri&lt;br /&gt;
				{&lt;br /&gt;
					el.content.sem.V();&lt;br /&gt;
					el.content.M--;&lt;br /&gt;
				}&lt;br /&gt;
				mutex.V();&lt;br /&gt;
			}&lt;br /&gt;
			else		// altrimenti si mette in attesa&lt;br /&gt;
			{&lt;br /&gt;
				el.content.M++;&lt;br /&gt;
				mutex.V();&lt;br /&gt;
				el.content.sem.P();&lt;br /&gt;
			}&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	if(!trovato)	// se non esiste lo crea&lt;br /&gt;
	{&lt;br /&gt;
		// NB: ho ancora la mutua esclusione&lt;br /&gt;
		struct S s;&lt;br /&gt;
		s.N = N;&lt;br /&gt;
		s.M = 1;&lt;br /&gt;
		s.sem = new Semaphore(0);&lt;br /&gt;
		L.insert_tail(S)	// inserisce nella lista (in coda)&lt;br /&gt;
		&lt;br /&gt;
		mutex.V():&lt;br /&gt;
		// si mette in attesa sul semaforo appena creato (NB: N!=1)&lt;br /&gt;
		L.tail().content.sem.P();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* NOTA: gli elementi della lista non vengono deallocati una volta liberato&lt;br /&gt;
	il semaforo; questo perchè è ancora possibile una race condition (rara)&lt;br /&gt;
	nel caso in cui un processo P1 stia per inserirsi su un semaforo già esistente&lt;br /&gt;
	(ha appena fatto mutex.V() ) e un altro P2 riesca ad entrare nel ciclo e&lt;br /&gt;
	liberare tutti =&amp;gt; P2 effettua una V in più e P1 esce subito dalla P&lt;br /&gt;
*/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2013.02.14&amp;diff=1126</id>
		<title>Prova Teorica 2013.02.14</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2013.02.14&amp;diff=1126"/>
		<updated>2015-05-26T16:58:51Z</updated>

		<summary type="html">&lt;p&gt;MV: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un monitor dualwriter che realizzi un doppio buffer limitato (ogni buffer ha ampiezza BUFSIZE) che consenta a uno scrittore di scrivere contemporaneamente due elementi che andranno rispettivamente nel primo e nel secondo buffer. Le letture :&lt;br /&gt;
  procedure entry void write(type1 e1, type2 e2);&lt;br /&gt;
  procedure entry type1 read1();&lt;br /&gt;
  procedure entry type2 read2();&lt;br /&gt;
La funzione write deve attendere che ci sia spazio in entrambi i buffer.&lt;br /&gt;
La funzione read attende che vi sia almeno un elemento nel buffer indicato.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------- SOLUZIONE DI MV -------------------------&lt;br /&gt;
&lt;br /&gt;
monitor dualwriter&lt;br /&gt;
{&lt;br /&gt;
	type1 buf1[BUFSIZE];&lt;br /&gt;
	type2 buf2[BUFSIZE];&lt;br /&gt;
	int next_r1, next_r2, n1, n2;&lt;br /&gt;
	// si ricorda che: next_w = (next_r+n)%BUFSIZE&lt;br /&gt;
	&lt;br /&gt;
	condition notempty1, notempty2;	// blocca in lettura se n=0&lt;br /&gt;
	condition canwrite;	// blocca in scrittura se n1=BUFSIZE || n2=BUFSIZE&lt;br /&gt;
	&lt;br /&gt;
	dualwriter()	// costruttore&lt;br /&gt;
	{&lt;br /&gt;
		n1 = n2 = next_r1 = next_r2 = 0;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry void write(type1 e1, type2 e2)&lt;br /&gt;
	{&lt;br /&gt;
		if(n1==BUFSIZE || n2==BUFSIZE)&lt;br /&gt;
			canwrite.wait();&lt;br /&gt;
		&lt;br /&gt;
		buf1[(next_r1+n1)%BUFSIZE] = e1;&lt;br /&gt;
		n1++;&lt;br /&gt;
		buf2[(next_r2+n2)%BUFSIZE] = e2;&lt;br /&gt;
		n2++;&lt;br /&gt;
		notempty1.signal();&lt;br /&gt;
		notempty2.signal();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry type1 read1()&lt;br /&gt;
	{&lt;br /&gt;
		type1 el;&lt;br /&gt;
		&lt;br /&gt;
		if(n1==0)&lt;br /&gt;
			notempty1.wait();&lt;br /&gt;
		&lt;br /&gt;
		el = buf1[next_r1];&lt;br /&gt;
		next_r1 = (next_r1+1)%BUFSIZE;&lt;br /&gt;
		n1--;&lt;br /&gt;
		&lt;br /&gt;
		// libera un processo sse è possibile scrivere in entrambi i buffer&lt;br /&gt;
		if(n1&amp;lt;BUFSIZE &amp;amp;&amp;amp; n2&amp;lt;BUFSIZE)&lt;br /&gt;
			canwrite.signal();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry type2 read2()&lt;br /&gt;
	{&lt;br /&gt;
		type2 el;&lt;br /&gt;
		&lt;br /&gt;
		if(n2==0)&lt;br /&gt;
			notempty1.wait();&lt;br /&gt;
		&lt;br /&gt;
		el = buf2[next_r2];&lt;br /&gt;
		next_r1 = (next_r1+1)%BUFSIZE;&lt;br /&gt;
		n2--;&lt;br /&gt;
		&lt;br /&gt;
		if(n1&amp;lt;BUFSIZE &amp;amp;&amp;amp; n2&amp;lt;BUFSIZE)&lt;br /&gt;
			canwrite.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Main_Page&amp;diff=1125</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=1125"/>
		<updated>2015-05-26T16:18:04Z</updated>

		<summary type="html">&lt;p&gt;MV: &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;
[[Prova Teorica 14-02-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Pratica Es.2 12-02-2009]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Teorica 13-05-2011]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Teorica 16-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Pratica 20-02-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Pratica 02-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Buffer Limitato]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1-2 Prova Pratica 30-05-2012]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 25-09-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 30-05-2012]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 23-06-09]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 25-09-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 20-06-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 29-05-14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 2 esame 29/05/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Grep piramidale (non tanto grep) esame 2.7.2003]]&lt;br /&gt;
&lt;br /&gt;
[[Ricerca e stampa MD5checksum (Prova pratica 21-01-2015)]]&lt;br /&gt;
&lt;br /&gt;
[[Differenza tra due sottoalberi del file system (Prova pratica 22-07-2011)]]&lt;br /&gt;
&lt;br /&gt;
[[Aggiorna cartelle (Prova pratica 23-01-2014)]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 prova pratica 29 maggio 2014]]&lt;br /&gt;
&lt;br /&gt;
[[Ampiezza di tutti i file di una directory divisi per suffisso (Prova pratica 29-05-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 12-09-11]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 25-01-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 22-06-2011]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 18-07-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 17-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica, 23-01-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica Esercizio 3 esami 17_07_12 - 17_06_14 - 19_07_10]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 23_01_14]]&lt;br /&gt;
&lt;br /&gt;
[[Albero binario 2002-07-23]]&lt;br /&gt;
&lt;br /&gt;
[[50 Sfumature di Fibonacci]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 20/06/12]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 17/06/14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 17 07 14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.01.2015]]&lt;br /&gt;
&lt;br /&gt;
[[bash scripting 2002 gennaio]]&lt;br /&gt;
&lt;br /&gt;
[[Process Race (Prova pratica 18-07-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Arduino web controller]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.06.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova_pratica_21_01_15]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 17.06.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 - 25.09.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20/02/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Demone ruba input]]&lt;br /&gt;
&lt;br /&gt;
[[wifi daemon]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Problema Dei Filosofi]]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/portability.tgz portability.tgz]&lt;br /&gt;
&lt;br /&gt;
[[listx.h commentato + esempio su container_of]]&lt;br /&gt;
&lt;br /&gt;
[[Congettura di Goldbach]]&lt;br /&gt;
&lt;br /&gt;
[[list segments]]&lt;br /&gt;
&lt;br /&gt;
[[Execv/fork su file aperto]]&lt;br /&gt;
&lt;br /&gt;
[[Angry_Children]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 12/02/2009]]&lt;br /&gt;
&lt;br /&gt;
[[(Programma C) Un quadrato nella matrice]]&lt;br /&gt;
&lt;br /&gt;
[[&amp;quot;classi&amp;quot;_in_C]]&lt;br /&gt;
&lt;br /&gt;
[[Esempi del 02 dicembre 2014]]&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>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2013.02.14&amp;diff=1124</id>
		<title>Prova Teorica 2013.02.14</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2013.02.14&amp;diff=1124"/>
		<updated>2015-05-26T16:16:46Z</updated>

		<summary type="html">&lt;p&gt;MV: Created page with &amp;quot;==Esercizio 1== &amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt; Scrivere un monitor dualwriter che realizzi un doppio buffer limitato (ogni buffer ha ampiezza BUFSIZE) che consenta a uno scrittore di sc...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un monitor dualwriter che realizzi un doppio buffer limitato (ogni buffer ha ampiezza BUFSIZE) che consenta a uno scrittore di scrivere contemporaneamente due elementi che andranno rispettivamente nel primo e nel secondo buffer. Le letture :&lt;br /&gt;
  procedure entry void write(type1 e1, type2 e2);&lt;br /&gt;
  procedure entry type1 read1();&lt;br /&gt;
  procedure entry type2 read2();&lt;br /&gt;
La funzione write deve attendere che ci sia spazio in entrambi i buffer.&lt;br /&gt;
La funzione read attende che vi sia almeno un elemento nel buffer indicato.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------- SOLUZIONE DI MV -------------------------&lt;br /&gt;
&lt;br /&gt;
monitor dualwriter&lt;br /&gt;
{&lt;br /&gt;
	type1 buf1[BUFSIZE];&lt;br /&gt;
	type2 buf2[BUFSIZE];&lt;br /&gt;
	int next_r1, next_r2, n1, n2;&lt;br /&gt;
	// si ricorda che: next_w = (next_r+n)%BUFSIZE&lt;br /&gt;
	&lt;br /&gt;
	condition notempty1, notempty2;	// blocca in lettura se n=0&lt;br /&gt;
	condition canwrite;	// blocca in scrittura se n1=BUFSIZE || n2=BUFSIZE&lt;br /&gt;
	&lt;br /&gt;
	dualwriter()	// costruttore&lt;br /&gt;
	{&lt;br /&gt;
		n1 = n2 = next_r1 = next_r2 = 0;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry void write(type1 e1, type2 e2)&lt;br /&gt;
	{&lt;br /&gt;
		if(n1==BUFSIZE || n2==BUFSIZE)&lt;br /&gt;
			canwrite.wait();&lt;br /&gt;
		&lt;br /&gt;
		buf1[(next_r1+n1)%BUFSIZE] = e1;&lt;br /&gt;
		n1++;&lt;br /&gt;
		buf2[(next_r2+n2)%BUFSIZE] = e2;&lt;br /&gt;
		n2++;&lt;br /&gt;
		notempty1.signal();&lt;br /&gt;
		notempty2.signal();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry type1 read1()&lt;br /&gt;
	{&lt;br /&gt;
		type1 el;&lt;br /&gt;
		&lt;br /&gt;
		if(n1==0)&lt;br /&gt;
			notempty1.wait();&lt;br /&gt;
		&lt;br /&gt;
		el = buf1[next_r1++];&lt;br /&gt;
		n1--;&lt;br /&gt;
		&lt;br /&gt;
		// libera un processo sse è possibile scrivere in entrambi i buffer&lt;br /&gt;
		if(n1&amp;lt;BUFSIZE &amp;amp;&amp;amp; n2&amp;lt;BUFSIZE)&lt;br /&gt;
			canwrite.signal();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry type2 read2()&lt;br /&gt;
	{&lt;br /&gt;
		type2 el;&lt;br /&gt;
		&lt;br /&gt;
		if(n2==0)&lt;br /&gt;
			notempty1.wait();&lt;br /&gt;
		&lt;br /&gt;
		el = buf2[next_r2++];&lt;br /&gt;
		n2--;&lt;br /&gt;
		&lt;br /&gt;
		if(n1&amp;lt;BUFSIZE &amp;amp;&amp;amp; n2&amp;lt;BUFSIZE)&lt;br /&gt;
			canwrite.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2011.05.13&amp;diff=1119</id>
		<title>Prova Teorica 2011.05.13</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2011.05.13&amp;diff=1119"/>
		<updated>2015-05-25T07:11:16Z</updated>

		<summary type="html">&lt;p&gt;MV: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un monitor reqq che gestisca Ncode di richieste.&lt;br /&gt;
I richiedenti chiamano la funzione che ha la seguente signature:&lt;br /&gt;
answer_t reqq.query(request_t request, int type);&lt;br /&gt;
Query deve fermare il processo richiedente fino a completamento della richiesta da parte di un gestore. Il valore di ritorno&lt;br /&gt;
e' la risposta del gestore.&lt;br /&gt;
Ci sono N gestori, uno per ogni tipo di richiesta, che si comportano come segue:&lt;br /&gt;
multiq_handler: process[i, i=0,..,N-1] {&lt;br /&gt;
  request_t req;&lt;br /&gt;
  int type;&lt;br /&gt;
  while (1) {&lt;br /&gt;
    req=reqq.getquery(i, &amp;amp;type);&lt;br /&gt;
    reqq.reply(i,handle(req, type));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
Normalmente le richieste vengono assegnate al gestore del tipo corrispondente (i==type), se non vi sono richieste di tale&lt;br /&gt;
tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti. Quando un gestore termina l'elaborazione&lt;br /&gt;
(funzione handle, da non implementare!) invia il risultato tramite la reply. Il valore passato alla reply deve essere restituito&lt;br /&gt;
al richiedente come valore di ritorno della funzione query. Se non vi sono richieste disponibili i gestori si fermano&lt;br /&gt;
attendendo nuove richieste.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------------- SOLUZIONE DI MV ----------------------------------------&lt;br /&gt;
&lt;br /&gt;
monitor reqq&lt;br /&gt;
{&lt;br /&gt;
	queue Q[N];	// array di N code&lt;br /&gt;
	answer_t A[N];	// variabili per salvare temporaneamente le risposte dei gestori&lt;br /&gt;
	condition notempy[N];	// ci si fermano i gestori se la risp. coda è vuota&lt;br /&gt;
	condition done[N];	// ci si fermano i processi in attesa della risposta&lt;br /&gt;
	int n_req[N];	// num. di richieste per ogni coda&lt;br /&gt;
	&lt;br /&gt;
	answer_t query(request_t request, int type)&lt;br /&gt;
	{&lt;br /&gt;
		Q[type].enqueue(request);&lt;br /&gt;
		n_req[type]++;&lt;br /&gt;
		notempy.signal();&lt;br /&gt;
		done.wait();&lt;br /&gt;
		return A[type];&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	request_t getrequest(int i, int* type)&lt;br /&gt;
	{&lt;br /&gt;
		*type = i;&lt;br /&gt;
		if(n_req[N] == 0)&lt;br /&gt;
			notempy.wait();&lt;br /&gt;
		return Q[i].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	void reply(int type, answer_t answer)&lt;br /&gt;
	{&lt;br /&gt;
		A[type] = answer;&lt;br /&gt;
		done.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ho provato a risolverlo pur non avendo ben capito una frase (&amp;quot;se non vi sono richieste di tale tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti&amp;quot;). Se notate errori avvisatemi!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------------- SOLUZIONE DI Maldus ----------------------------------------&lt;br /&gt;
monitor reqq{&lt;br /&gt;
	request_t queue Q[N];	&lt;br /&gt;
	condition[] done = new condition[N];	&lt;br /&gt;
	condition notempty;	// una sola condizione per controllare quando la coda delle richieste è vuota;&lt;br /&gt;
	answer_t A[N];&lt;br /&gt;
	int longest;&lt;br /&gt;
&lt;br /&gt;
	reqq(){&lt;br /&gt;
		longest = 0 ;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry answer_t query( request_t request, int type){&lt;br /&gt;
		Q[type].enqueue(request);&lt;br /&gt;
		if( Q[type].lenght() &amp;gt; Q[longest].lenght() ) longest = type;&lt;br /&gt;
		notempty.signal();&lt;br /&gt;
		done[type].wait();&lt;br /&gt;
		return A[type];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry request_t getquery( int i, int* type){&lt;br /&gt;
		if( Q[i].empty() ){&lt;br /&gt;
			if( longest == 0 ) notempty.wait();&lt;br /&gt;
			i = longest;&lt;br /&gt;
		}&lt;br /&gt;
		*type = i ;&lt;br /&gt;
		return Q[i].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void reply( int type, answer_t answer){&lt;br /&gt;
		A[type] = answer;&lt;br /&gt;
		done.signal();&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Interpreto la frase &amp;quot;se non vi sono richieste di tale tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti&amp;quot; considerando appunto il tipo per il quale ci sono più richieste ( se quello specificato invece non ne ha) nella funzione getquery: in quest'ottica ho pensato che la condizione notempty dovesse essere singola, perchè se un gestore può gestire anche una richiesta diversa dal tipo specificato, non importa quale richiesta viene aggiunta. Per il resto è praticamente identico alla soluzione di MV.&lt;br /&gt;
&lt;br /&gt;
==Esercizio 2==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Facendo uso di semafori ordinari implementare le funzioni lifocs_enter e lifocs_exit che realizzino una critical section LIFO.&lt;br /&gt;
I processi per usare la critical section LIFO usano il seguente protocollo:&lt;br /&gt;
lifocs_enter()&lt;br /&gt;
.... codice critico&lt;br /&gt;
lifocs_exit()&lt;br /&gt;
quando un processo rilascia la sezione critica e ci sono processi in attesa di entrare, deve venir assegnata la sezione critica al processo che ha fatto l'ultima richiesta (in ordine di tempo).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------- SOLUZIONE DI MV -----------------------------&lt;br /&gt;
&lt;br /&gt;
// la cosa più semplice che mi è venuta in mente è di allocare dinamicamente uno stack di semafori&lt;br /&gt;
shared Stack&amp;lt;Semaphore&amp;gt; S = new Stack&amp;lt;Semaphore&amp;gt;();&lt;br /&gt;
shared Semaphore mutex = new Semaphore(1);&lt;br /&gt;
shared int n_proc = 0;&lt;br /&gt;
&lt;br /&gt;
lifocs_enter()&lt;br /&gt;
{&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if(n_proc++ == 0)&lt;br /&gt;
	{&lt;br /&gt;
		mutex.V();&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		Semaphore sem = new Semaphore(0);&lt;br /&gt;
		S.push(sem);&lt;br /&gt;
		mutex.V();&lt;br /&gt;
		sem.P();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
lifocs_exit()&lt;br /&gt;
{&lt;br /&gt;
	Semaphore sem;&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if(--n_proc == 0)&lt;br /&gt;
	{&lt;br /&gt;
		mutex.V();&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		sem = S.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
		sem.V();&lt;br /&gt;
		free(sem);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Un servizio di message passing a canale prevede che ogni spedizione e ricezione di un messaggio faccia riferimento a “canale” e non ad un processo.&lt;br /&gt;
L'interfaccia e' la seguente:&lt;br /&gt;
  n=channel_join_create(id); /* crea un canale con l'id specificato se non esiste, altrimenti incrementa il numero dei processi che stanno usando il canale, restituisce il numero di processi che condividono il canale. l'operazione e' atomica */&lt;br /&gt;
  channel_send(id,msg); /* spedisce in modo asincrono un messaggio sul canale id */&lt;br /&gt;
  msg=channel_receive(id); /* riceve un messaggio sul canale specificato, se piu' processi si fermano in attesa di un messaggio dallo stesso canale, ogni messaggio viene recapitato al processo che per primo ha richiesto la channel_receive */&lt;br /&gt;
  channel_leave_delete(id); /* decrementa il numero dei processi utilizzatori del canale, il canale viene cancellato&lt;br /&gt;
quando non ha piu' utilizzatori. L'operazione e' atomica. */&lt;br /&gt;
Implementare un supporto per sezioni critiche che faccia uso del message passing a canale. (le funzioni da implementare sono csenter, csexit).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// --------------------------------- SOLUZIONE DI MV -----------------------------------------&lt;br /&gt;
&lt;br /&gt;
const int ID = 1;	// si utilizza un unico canale&lt;br /&gt;
&lt;br /&gt;
void cs_enter()&lt;br /&gt;
{&lt;br /&gt;
	// se c'è almeno un altro processo si mette in attesa di un messaggio di via libera, altrimenti semplicemente crea il canale&lt;br /&gt;
	if(channel_join_create(ID) &amp;gt; 1)&lt;br /&gt;
		channel_receive(ID);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cs_exit()&lt;br /&gt;
{&lt;br /&gt;
	// libera il primo processo in attesa di receive sul canale&lt;br /&gt;
	// (si suppone che un messaggio spedito su un canale vuoto venga semplicemente perduto)&lt;br /&gt;
	channel_send(ID,&amp;quot;go&amp;quot;);&lt;br /&gt;
	channel_leave_delete(ID);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2011.05.13&amp;diff=1118</id>
		<title>Prova Teorica 2011.05.13</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2011.05.13&amp;diff=1118"/>
		<updated>2015-05-25T06:54:43Z</updated>

		<summary type="html">&lt;p&gt;MV: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un monitor reqq che gestisca Ncode di richieste.&lt;br /&gt;
I richiedenti chiamano la funzione che ha la seguente signature:&lt;br /&gt;
answer_t reqq.query(request_t request, int type);&lt;br /&gt;
Query deve fermare il processo richiedente fino a completamento della richiesta da parte di un gestore. Il valore di ritorno&lt;br /&gt;
e' la risposta del gestore.&lt;br /&gt;
Ci sono N gestori, uno per ogni tipo di richiesta, che si comportano come segue:&lt;br /&gt;
multiq_handler: process[i, i=0,..,N-1] {&lt;br /&gt;
  request_t req;&lt;br /&gt;
  int type;&lt;br /&gt;
  while (1) {&lt;br /&gt;
    req=reqq.getquery(i, &amp;amp;type);&lt;br /&gt;
    reqq.reply(i,handle(req, type));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
Normalmente le richieste vengono assegnate al gestore del tipo corrispondente (i==type), se non vi sono richieste di tale&lt;br /&gt;
tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti. Quando un gestore termina l'elaborazione&lt;br /&gt;
(funzione handle, da non implementare!) invia il risultato tramite la reply. Il valore passato alla reply deve essere restituito&lt;br /&gt;
al richiedente come valore di ritorno della funzione query. Se non vi sono richieste disponibili i gestori si fermano&lt;br /&gt;
attendendo nuove richieste.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------------- SOLUZIONE DI MV ----------------------------------------&lt;br /&gt;
&lt;br /&gt;
monitor reqq&lt;br /&gt;
{&lt;br /&gt;
	queue Q[N];	// array di N code&lt;br /&gt;
	answer_t A[N];	// variabili per salvare temporaneamente le risposte dei gestori&lt;br /&gt;
	condition notempy[N];	// ci si fermano i gestori se la risp. coda è vuota&lt;br /&gt;
	condition done[N];	// ci si fermano i processi in attesa della risposta&lt;br /&gt;
	int n_req[N];	// num. di richieste per ogni coda&lt;br /&gt;
	&lt;br /&gt;
	answer_t query(request_t request, int type)&lt;br /&gt;
	{&lt;br /&gt;
		Q[type].enqueue(request);&lt;br /&gt;
		n_req[type]++;&lt;br /&gt;
		notempy.signal();&lt;br /&gt;
		done.wait();&lt;br /&gt;
		return A[type];&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	request_t getrequest(int i, int* type)&lt;br /&gt;
	{&lt;br /&gt;
		*type = i;&lt;br /&gt;
		if(n_req[N] == 0)&lt;br /&gt;
			notempy.wait();&lt;br /&gt;
		return Q[i].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	void reply(int type, answer_t answer)&lt;br /&gt;
	{&lt;br /&gt;
		A[type] = answer;&lt;br /&gt;
		done.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ho provato a risolverlo pur non avendo ben capito una frase (&amp;quot;se non vi sono richieste di tale tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti&amp;quot;). Se notate errori avvisatemi!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------------- SOLUZIONE DI Maldus ----------------------------------------&lt;br /&gt;
monitor reqq{&lt;br /&gt;
	request_t queue Q[N];	&lt;br /&gt;
	condition[] done = new condition[N];	&lt;br /&gt;
	condition notempty;	// una sola condizione per controllare quando la coda delle richieste è vuota;&lt;br /&gt;
	answer_t A[N];&lt;br /&gt;
	int longest;&lt;br /&gt;
&lt;br /&gt;
	reqq(){&lt;br /&gt;
		longest = 0 ;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry answer_t query( request_t request, int type){&lt;br /&gt;
		Q[type].enqueue(request);&lt;br /&gt;
		if( Q[type].lenght() &amp;gt; Q[longest].lenght() ) longest = type;&lt;br /&gt;
		notempty.signal();&lt;br /&gt;
		done[type].wait();&lt;br /&gt;
		return A[type];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry request_t getquery( int i, int* type){&lt;br /&gt;
		if( Q[i].empty() ){&lt;br /&gt;
			if( longest == 0 ) notempty.wait();&lt;br /&gt;
			i = longest;&lt;br /&gt;
		}&lt;br /&gt;
		*type = i ;&lt;br /&gt;
		return Q[i].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void reply( int type, answer_t answer){&lt;br /&gt;
		A[type] = answer;&lt;br /&gt;
		done.signal();&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Interpreto la frase &amp;quot;se non vi sono richieste di tale tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti&amp;quot; considerando appunto il tipo per il quale ci sono più richieste ( se quello specificato invece non ne ha) nella funzione getquery: in quest'ottica ho pensato che la condizione notempty dovesse essere singola, perchè se un gestore può gestire anche una richiesta diversa dal tipo specificato, non importa quale richiesta viene aggiunta. Per il resto è praticamente identico alla soluzione di MV.&lt;br /&gt;
&lt;br /&gt;
==Esercizio 2==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Facendo uso di semafori ordinari implementare le funzioni lifocs_enter e lifocs_exit che realizzino una critical section LIFO.&lt;br /&gt;
I processi per usare la critical section LIFO usano il seguente protocollo:&lt;br /&gt;
lifocs_enter()&lt;br /&gt;
.... codice critico&lt;br /&gt;
lifocs_exit()&lt;br /&gt;
quando un processo rilascia la sezione critica e ci sono processi in attesa di entrare, deve venir assegnata la sezione critica al processo che ha fatto l'ultima richiesta (in ordine di tempo).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------- SOLUZIONE DI MV -----------------------------&lt;br /&gt;
&lt;br /&gt;
// la cosa più semplice che mi è venuta in mente è di allocare dinamicamente uno stack di semafori&lt;br /&gt;
shared Stack&amp;lt;Semaphore&amp;gt; S = new Stack&amp;lt;Semaphore&amp;gt;();&lt;br /&gt;
shared Semaphore mutex = new Semaphore(1);&lt;br /&gt;
shared int n_proc = 0;&lt;br /&gt;
&lt;br /&gt;
lifocs_enter()&lt;br /&gt;
{&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if(n_proc++ == 0)&lt;br /&gt;
	{&lt;br /&gt;
		mutex.V();&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		Semaphore sem = new Semaphore(0);&lt;br /&gt;
		S.push(sem);&lt;br /&gt;
		mutex.V();&lt;br /&gt;
		sem.P();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
lifocs_exit()&lt;br /&gt;
{&lt;br /&gt;
	Semaphore sem;&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if(--n_proc == 0)&lt;br /&gt;
	{&lt;br /&gt;
		mutex.V();&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		sem = S.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
		sem.V();&lt;br /&gt;
		free(sem);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Main_Page&amp;diff=1112</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=1112"/>
		<updated>2015-05-22T12:53:05Z</updated>

		<summary type="html">&lt;p&gt;MV: &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;
[[Prova Teorica 13-05-2011]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Teorica 16-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Pratica 20-02-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova Pratica 02-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Buffer Limitato]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1-2 Prova Pratica 30-05-2012]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 25-09-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 30-05-2012]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 23-06-09]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 25-09-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 20-06-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 29-05-14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 2 esame 29/05/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Grep piramidale (non tanto grep) esame 2.7.2003]]&lt;br /&gt;
&lt;br /&gt;
[[Ricerca e stampa MD5checksum (Prova pratica 21-01-2015)]]&lt;br /&gt;
&lt;br /&gt;
[[Differenza tra due sottoalberi del file system (Prova pratica 22-07-2011)]]&lt;br /&gt;
&lt;br /&gt;
[[Aggiorna cartelle (Prova pratica 23-01-2014)]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 prova pratica 29 maggio 2014]]&lt;br /&gt;
&lt;br /&gt;
[[Ampiezza di tutti i file di una directory divisi per suffisso (Prova pratica 29-05-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 12-09-11]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 25-01-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 22-06-2011]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 18-07-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 17-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica, 23-01-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica Esercizio 3 esami 17_07_12 - 17_06_14 - 19_07_10]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 23_01_14]]&lt;br /&gt;
&lt;br /&gt;
[[Albero binario 2002-07-23]]&lt;br /&gt;
&lt;br /&gt;
[[50 Sfumature di Fibonacci]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 20/06/12]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 17/06/14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 17 07 14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.01.2015]]&lt;br /&gt;
&lt;br /&gt;
[[bash scripting 2002 gennaio]]&lt;br /&gt;
&lt;br /&gt;
[[Process Race (Prova pratica 18-07-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Arduino web controller]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.06.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova_pratica_21_01_15]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 17.06.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 - 25.09.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20/02/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Demone ruba input]]&lt;br /&gt;
&lt;br /&gt;
[[wifi daemon]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Problema Dei Filosofi]]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/portability.tgz portability.tgz]&lt;br /&gt;
&lt;br /&gt;
[[listx.h commentato + esempio su container_of]]&lt;br /&gt;
&lt;br /&gt;
[[Congettura di Goldbach]]&lt;br /&gt;
&lt;br /&gt;
[[list segments]]&lt;br /&gt;
&lt;br /&gt;
[[Execv/fork su file aperto]]&lt;br /&gt;
&lt;br /&gt;
[[Angry_Children]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 12/02/2009]]&lt;br /&gt;
&lt;br /&gt;
[[(Programma C) Un quadrato nella matrice]]&lt;br /&gt;
&lt;br /&gt;
[[&amp;quot;classi&amp;quot;_in_C]]&lt;br /&gt;
&lt;br /&gt;
[[Esempi del 02 dicembre 2014]]&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>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2011.05.13&amp;diff=1111</id>
		<title>Prova Teorica 2011.05.13</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Teorica_2011.05.13&amp;diff=1111"/>
		<updated>2015-05-22T12:52:13Z</updated>

		<summary type="html">&lt;p&gt;MV: Created page with &amp;quot;==Esercizio 1== &amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt; Scrivere un monitor reqq che gestisca Ncode di richieste. I richiedenti chiamano la funzione che ha la seguente signature: answer_t reqq.q...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un monitor reqq che gestisca Ncode di richieste.&lt;br /&gt;
I richiedenti chiamano la funzione che ha la seguente signature:&lt;br /&gt;
answer_t reqq.query(request_t request, int type);&lt;br /&gt;
Query deve fermare il processo richiedente fino a completamento della richiesta da parte di un gestore. Il valore di ritorno&lt;br /&gt;
e' la risposta del gestore.&lt;br /&gt;
Ci sono N gestori, uno per ogni tipo di richiesta, che si comportano come segue:&lt;br /&gt;
multiq_handler: process[i, i=0,..,N-1] {&lt;br /&gt;
  request_t req;&lt;br /&gt;
  int type;&lt;br /&gt;
  while (1) {&lt;br /&gt;
    req=reqq.getquery(i, &amp;amp;type);&lt;br /&gt;
    reqq.reply(i,handle(req, type));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
Normalmente le richieste vengono assegnate al gestore del tipo corrispondente (i==type), se non vi sono richieste di tale&lt;br /&gt;
tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti. Quando un gestore termina l'elaborazione&lt;br /&gt;
(funzione handle, da non implementare!) invia il risultato tramite la reply. Il valore passato alla reply deve essere restituito&lt;br /&gt;
al richiedente come valore di ritorno della funzione query. Se non vi sono richieste disponibili i gestori si fermano&lt;br /&gt;
attendendo nuove richieste.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// ------------------------------- SOLUZIONE DI MV ----------------------------------------&lt;br /&gt;
&lt;br /&gt;
monitor reqq&lt;br /&gt;
{&lt;br /&gt;
	queue Q[N];	// array di N code&lt;br /&gt;
	answer_t A[N];	// variabili per salvare temporaneamente le risposte dei gestori&lt;br /&gt;
	condition notempy[N];	// ci si fermano i gestori se la risp. coda è vuota&lt;br /&gt;
	condition done[N];	// ci si fermano i processi in attesa della risposta&lt;br /&gt;
	int n_req[N];	// num. di richieste per ogni coda&lt;br /&gt;
	&lt;br /&gt;
	answer_t query(request_t request, int type)&lt;br /&gt;
	{&lt;br /&gt;
		Q[type].enqueue(request);&lt;br /&gt;
		n_req[type]++;&lt;br /&gt;
		notempy.signal();&lt;br /&gt;
		done.wait();&lt;br /&gt;
		return A[type];&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	request_t getrequest(int i, int* type)&lt;br /&gt;
	{&lt;br /&gt;
		*type = i;&lt;br /&gt;
		if(n_req[N] == 0)&lt;br /&gt;
			notempy.wait();&lt;br /&gt;
		return Q[i].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	void reply(int type, answer_t answer)&lt;br /&gt;
	{&lt;br /&gt;
		A[type] = answer;&lt;br /&gt;
		done.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ho provato a risolverlo pur non avendo ben capito una frase (&amp;quot;se non vi sono richieste di tale tipo elabora una richiesta del tipo con la piu' lunga coda di richieste pendenti&amp;quot;). Se notate errori avvisatemi!&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizio_3,_prova_pratica,_18-07-2013&amp;diff=1109</id>
		<title>Esercizio 3, prova pratica, 18-07-2013</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizio_3,_prova_pratica,_18-07-2013&amp;diff=1109"/>
		<updated>2015-05-19T07:24:19Z</updated>

		<summary type="html">&lt;p&gt;MV: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Testo==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un programma python o uno script bash che cataloghi per nome tutti i file presenti in un sottoalbero.&lt;br /&gt;
nameindex dir1 dir2&lt;br /&gt;
crea nel file dir2 un link simbolico ad ogni file contenuto nell'albero che ha come radice dir1. Quando sono presenti piu' file&lt;br /&gt;
con lo stesso nome in diverse directory all'interno di dir1, viene posto un suffisso numerico al nome del link simbolico&lt;br /&gt;
se dir1 contiene i file pippo, pluto e paperino e la directory paperopoli e quest'ultima contiene i file paperino, qui quo e qua,&lt;br /&gt;
all'interno di dir2 divranno essere contenuti i seguenti link simbolici:&lt;br /&gt;
pippo → dir1/pippo&lt;br /&gt;
pluto → dir1/pluto&lt;br /&gt;
paperino → dir1/paperino&lt;br /&gt;
paperino1 → dir1/paperopoli/paperino&lt;br /&gt;
qui → dir1/paperopoli/qui&lt;br /&gt;
quo → dir1/paperopoli/quo&lt;br /&gt;
qua → dir1/paperopoli/qua&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Soluzione di Krusty===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os, sys&lt;br /&gt;
from stat import *&lt;br /&gt;
&lt;br /&gt;
exist={}&lt;br /&gt;
&lt;br /&gt;
def Scan(pathname):&lt;br /&gt;
&lt;br /&gt;
	for f in os.listdir(pathname):&lt;br /&gt;
		path = os.path.join(pathname,f)&lt;br /&gt;
		s = os.stat(path)&lt;br /&gt;
		if S_ISREG(s.st_mode):&lt;br /&gt;
			if f not in exist:&lt;br /&gt;
				exist[f] = 1&lt;br /&gt;
				os.symlink(path,f)	&lt;br /&gt;
			else:&lt;br /&gt;
				n = exist[f]&lt;br /&gt;
				exist[f] = exist[f] + 1&lt;br /&gt;
				os.symlink(path,(f+str(n)))	&lt;br /&gt;
				&lt;br /&gt;
		elif S_ISDIR(s.st_mode):	&lt;br /&gt;
			Scan(path)&lt;br /&gt;
&lt;br /&gt;
#main&lt;br /&gt;
&lt;br /&gt;
if not os.path.isdir(sys.argv[2]):&lt;br /&gt;
    os.makedirs(sys.argv[2])&lt;br /&gt;
&lt;br /&gt;
os.chdir(sys.argv[2])&lt;br /&gt;
Scan(sys.argv[1])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Soluzione di MV==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
&lt;br /&gt;
if (( $# != 2 ))&lt;br /&gt;
then&lt;br /&gt;
	echo &amp;quot;Usage: nameindex dir1 dir2&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [[ $1 = /* ]] # verifico se $1 è un path assoluto o relativo (è necessario assoluto per i link)&lt;br /&gt;
then &lt;br /&gt;
	dir1=$1&lt;br /&gt;
else&lt;br /&gt;
	dir1=`pwd`/$1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for i in `find $dir`	# scandisco l'albero&lt;br /&gt;
do&lt;br /&gt;
	if [ -f $i ]&lt;br /&gt;
	then&lt;br /&gt;
		filename=`basename $i`		# ricavo il nome del file senza percorso&lt;br /&gt;
		&lt;br /&gt;
		if [ ! -f $2/$filename ] 	# se è il primo file trovato con quel nome&lt;br /&gt;
		then						# creo il link con lo stesso nome&lt;br /&gt;
			ln -s $dir1/$i $2/$filename&lt;br /&gt;
		else			# altrimento cerco il primo numero n&amp;gt;0 non ancora usato come suffisso&lt;br /&gt;
			n=1&lt;br /&gt;
			while [ -f $2/${filename}${n} ]&lt;br /&gt;
			do&lt;br /&gt;
				(( n=$n+1 ))&lt;br /&gt;
			done&lt;br /&gt;
			ln -s $dir1/$i $2/$filename$n&lt;br /&gt;
		fi&lt;br /&gt;
	fi&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Main_Page&amp;diff=1094</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=1094"/>
		<updated>2015-05-12T20:33:55Z</updated>

		<summary type="html">&lt;p&gt;MV: &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;
[[Buffer Limitato]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1-2 Prova Pratica 30-05-2012]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 25-09-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 30-05-2012]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 23-06-09]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 25-09-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 20-06-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 29-05-14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 2 esame 29/05/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Grep piramidale (non tanto grep) esame 2.7.2003]]&lt;br /&gt;
&lt;br /&gt;
[[Ricerca e stampa MD5checksum (Prova pratica 21-01-2015)]]&lt;br /&gt;
&lt;br /&gt;
[[Linker fisico (Prova pratica 20-02-2014)]]&lt;br /&gt;
&lt;br /&gt;
[[Differenza tra due sottoalberi del file system (Prova pratica 22-07-2011)]]&lt;br /&gt;
&lt;br /&gt;
[[Aggiorna cartelle (Prova pratica 23-01-2014)]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 prova pratica 29 maggio 2014]]&lt;br /&gt;
&lt;br /&gt;
[[Ampiezza di tutti i file di una directory divisi per suffisso (Prova pratica 29-05-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 12-09-11]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 25-01-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 22-06-2011]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 18-07-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 17-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica, 23-01-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica Esercizio 3 esami 17_07_12 - 17_06_14 - 19_07_10]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 23_01_14]]&lt;br /&gt;
&lt;br /&gt;
[[Albero binario 2002-07-23]]&lt;br /&gt;
&lt;br /&gt;
[[50 Sfumature di Fibonacci]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 20/06/12]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 17/06/14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 17 07 14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.01.2015]]&lt;br /&gt;
&lt;br /&gt;
[[bash scripting 2002 gennaio]]&lt;br /&gt;
&lt;br /&gt;
[[Process Race (Prova pratica 18-07-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Arduino web controller]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.06.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova_pratica_21_01_15]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 17.06.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 - 25.09.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20/02/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Demone ruba input]]&lt;br /&gt;
&lt;br /&gt;
[[wifi daemon]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Problema Dei Filosofi]]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/portability.tgz portability.tgz]&lt;br /&gt;
&lt;br /&gt;
[[listx.h commentato + esempio su container_of]]&lt;br /&gt;
&lt;br /&gt;
[[Congettura di Goldbach]]&lt;br /&gt;
&lt;br /&gt;
[[list segments]]&lt;br /&gt;
&lt;br /&gt;
[[Execv/fork su file aperto]]&lt;br /&gt;
&lt;br /&gt;
[[Angry_Children]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 12/02/2009]]&lt;br /&gt;
&lt;br /&gt;
[[(Programma C) Un quadrato nella matrice]]&lt;br /&gt;
&lt;br /&gt;
[[&amp;quot;classi&amp;quot;_in_C]]&lt;br /&gt;
&lt;br /&gt;
[[Esempi del 02 dicembre 2014]]&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>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Buffer_Limitato&amp;diff=1093</id>
		<title>Buffer Limitato</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Buffer_Limitato&amp;diff=1093"/>
		<updated>2015-05-12T20:33:27Z</updated>

		<summary type="html">&lt;p&gt;MV: Created page with &amp;quot;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt; Esercizio di programmazione concorrente: Il programma genera 2 thread. Il primo di questi, detto producer, prende i valori da stdin e li scrive su un buff...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Esercizio di programmazione concorrente:&lt;br /&gt;
Il programma genera 2 thread.&lt;br /&gt;
Il primo di questi, detto producer, prende i valori da stdin e li scrive su un buffer.&lt;br /&gt;
Il secondo, detto consumer, legge i valori dal buffer e li scrive su un file.&lt;br /&gt;
Requisiti:&lt;br /&gt;
- Il buffer è usato come array circolare&lt;br /&gt;
- Producer non deve scrivere su valori non ancora letti&lt;br /&gt;
- Consumer deve leggere i valori in ordine e senza ripetizioni&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Soluzione di MV, usando i semafori ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&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;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;semaphore.h&amp;gt;&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;
&lt;br /&gt;
#define DIM_BUF 10&lt;br /&gt;
#define THREAD_SHARED 0&lt;br /&gt;
&lt;br /&gt;
char buffer[DIM_BUF];&lt;br /&gt;
int next_write = 0, next_read = 0;	// indici sul buffer&lt;br /&gt;
sem_t empty;	// semaforo: consumer si blocca su di esso quando il buffer è vuoto&lt;br /&gt;
sem_t full;		// semaforo: producer si blocca su di esso quando il buffer è pieno&lt;br /&gt;
&lt;br /&gt;
void* producer_routine(void *arg)&lt;br /&gt;
{&lt;br /&gt;
	char c;&lt;br /&gt;
	while(scanf(&amp;quot;%c&amp;quot;,&amp;amp;c) != EOF)	// legge (&amp;quot;produce&amp;quot;) un carattere da stdin&lt;br /&gt;
	{&lt;br /&gt;
		if(sem_wait(&amp;amp;full) != 0)	// si blocca se il buffer è pieno&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error %i in producer: %s&amp;quot;,errno,strerror(errno));&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		buffer[next_write] = c;&lt;br /&gt;
		next_write = (next_write+1)%DIM_BUF;&lt;br /&gt;
	&lt;br /&gt;
		if(sem_post(&amp;amp;empty) != 0)	// segnala un nuovo carattere non letto sul buffer&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error %i in producer: %s&amp;quot;,errno,strerror(errno));&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* consumer_routine(void * arg)&lt;br /&gt;
{&lt;br /&gt;
	FILE *file;&lt;br /&gt;
	&lt;br /&gt;
	if( (file = fopen(&amp;quot;./consumed.txt&amp;quot;,&amp;quot;a&amp;quot;)) == NULL)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error %i in consumer: %s&amp;quot;,errno,strerror(errno));&lt;br /&gt;
		return NULL;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		char c;&lt;br /&gt;
		&lt;br /&gt;
		if(sem_wait(&amp;amp;empty) != 0)	// se il buffer è vuoto si blocca&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error %i in consumer: %s&amp;quot;,errno,strerror(errno));&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		fprintf(file,&amp;quot;%c&amp;quot;,buffer[next_read]);&lt;br /&gt;
		next_read = (next_read+1)%DIM_BUF;&lt;br /&gt;
		&lt;br /&gt;
		if(sem_post(&amp;amp;full) != 0)	// segnala che si è liberato un posto sul buffer&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error %i in consumer: %s&amp;quot;,errno,strerror(errno));&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	close(file);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
	pthread_t producer, consumer;&lt;br /&gt;
	int *error, i;&lt;br /&gt;
	&lt;br /&gt;
	for(i=0; i&amp;lt; DIM_BUF; i++)&lt;br /&gt;
		buffer[i] = 0;&lt;br /&gt;
	&lt;br /&gt;
	if(sem_init(&amp;amp;empty,THREAD_SHARED,0) != 0)	// inizializzato a 0 perchè il buffer è vuoto&lt;br /&gt;
		return errno;&lt;br /&gt;
	if(sem_init(&amp;amp;full,THREAD_SHARED,DIM_BUF) != 0)	// servono DIM_BUF scritture per riempirlo&lt;br /&gt;
		return errno;&lt;br /&gt;
	&lt;br /&gt;
	pthread_create(&amp;amp;producer,NULL,&amp;amp;producer_routine,NULL);&lt;br /&gt;
	pthread_create(&amp;amp;consumer,NULL,&amp;amp;consumer_routine,NULL);&lt;br /&gt;
	&lt;br /&gt;
	pthread_join(producer, (void**)&amp;amp;error);	// aspetta la terminazione di producer&lt;br /&gt;
	printf(&amp;quot;End.\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_2011.06.22&amp;diff=1047</id>
		<title>Prova Pratica 2011.06.22</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_2011.06.22&amp;diff=1047"/>
		<updated>2015-04-20T07:20:03Z</updated>

		<summary type="html">&lt;p&gt;MV: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere uno script bash o un programma python che metta in ordine tutti i file di un sottoalbero dal piu' vecchio al piu' recente.&lt;br /&gt;
La stampa finale deve mostrare solamente il path relativo dei file.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Soluzione di MV (bash)==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
SCRIPT=$0&lt;br /&gt;
&lt;br /&gt;
# il primo script è lanciato con 1 parametro: directory&lt;br /&gt;
# le chiamate ricorsive son fatte con 2 parametri: directory file&lt;br /&gt;
if (( $# &amp;lt; 1 ))&lt;br /&gt;
then&lt;br /&gt;
	echo &amp;quot;inserire il pathname di una directory come parametro&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ ! -d $1 ]&lt;br /&gt;
then&lt;br /&gt;
	echo &amp;quot;`pwd`/$1 non esiste o non è una directory&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
DIR=$1&lt;br /&gt;
&lt;br /&gt;
if (( $# == 2))&lt;br /&gt;
then&lt;br /&gt;
	FILE=$2		# gli script ricorsivi usano lo stesso file del chiamante&lt;br /&gt;
else&lt;br /&gt;
	FILE=tmp$$	# lo script iniziale crea un file temporaneo&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# salvo nel file temporaneo le informazioni che mi interessano di tutti i file&lt;br /&gt;
for i in `ls $DIR`	&lt;br /&gt;
do&lt;br /&gt;
	if [ -f $DIR/$i ]&lt;br /&gt;
	then&lt;br /&gt;
		stat -c &amp;quot;%y %n&amp;quot; $DIR/$i &amp;gt;&amp;gt; $FILE&lt;br /&gt;
	elif [ -d $DIR/$i ]&lt;br /&gt;
	then&lt;br /&gt;
		$SCRIPT $DIR/$i $FILE	# chiamata ricorsiva&lt;br /&gt;
	fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
# eseguito solo dal primo script (non da quelli ricorsivi)&lt;br /&gt;
if (( $# != 2))&lt;br /&gt;
then&lt;br /&gt;
	BEGIN=37	# indica il primo carattere da stampare per ogni riga&lt;br /&gt;
				# cioè tutti quelli prima indicano la data di modifica del file&lt;br /&gt;
	sort $FILE | cut --characters=&amp;quot;$BEGIN-&amp;quot;	# riordino per data e stampo il nome&lt;br /&gt;
	rm $FILE&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Soluzione di MV (python)==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
if(len(sys.argv) != 1):&lt;br /&gt;
	DIR = sys.argv[1];&lt;br /&gt;
else:&lt;br /&gt;
	print(&amp;quot;inserire il pathname di una directory come parametro&amp;quot;)&lt;br /&gt;
	exit(1)&lt;br /&gt;
&lt;br /&gt;
if os.path.isdir(DIR):&lt;br /&gt;
	os.chdir(DIR)&lt;br /&gt;
else:&lt;br /&gt;
	print(&amp;quot;percorso non valido&amp;quot;)&lt;br /&gt;
	exit(1)&lt;br /&gt;
&lt;br /&gt;
# NOTA: DIR mantiene sempre il percorso relativo dalla directory passata come parametro&lt;br /&gt;
def scanTree(DIR,lista):&lt;br /&gt;
&lt;br /&gt;
	c = len(DIR)-1&lt;br /&gt;
	if(DIR[c] == '/' and c != 0):&lt;br /&gt;
		DIR = DIR[0:c]&lt;br /&gt;
	&lt;br /&gt;
	for el in os.listdir(DIR):&lt;br /&gt;
		el = DIR+&amp;quot;/&amp;quot;+el&lt;br /&gt;
		if os.path.isdir(el):&lt;br /&gt;
			scanTree(el, lista)&lt;br /&gt;
		elif os.path.isfile(el):&lt;br /&gt;
			mtime = os.stat(el).st_mtime&lt;br /&gt;
			lista.append((mtime,el));	# memorizzo i file in una tupla (mtime, path)&lt;br /&gt;
			&lt;br /&gt;
lista = []&lt;br /&gt;
scanTree('.', lista)&lt;br /&gt;
lista.sort()	#NB: le tuple vengono ordinate in base al loro primo elemento (mtime)&lt;br /&gt;
for i in lista:&lt;br /&gt;
	print(i[1])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Main_Page&amp;diff=1014</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=1014"/>
		<updated>2015-04-13T09:52:13Z</updated>

		<summary type="html">&lt;p&gt;MV: &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;
[[Esercizio 3 Prova Pratica 22-06-2011]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 18-07-2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica, 17-07-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica, 23-01-2014]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica Esercizio 3 esami 17_07_12 - 17_06_14 - 19_07_10]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 23_01_14]]&lt;br /&gt;
&lt;br /&gt;
[[Ampiezza di tutti i file di una directory divisi per suffisso (Prova pratica 29-05-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Albero binario 2002-07-23]]&lt;br /&gt;
&lt;br /&gt;
[[50 Sfumature di Fibonacci]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 Prova Pratica 20/06/12]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3 Prova Pratica 17/06/14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 3, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova pratica 17 07 14]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.01.2015]]&lt;br /&gt;
&lt;br /&gt;
[[bash scripting 2002 gennaio]]&lt;br /&gt;
&lt;br /&gt;
[[Process Race (Prova pratica 18-07-2013)]]&lt;br /&gt;
&lt;br /&gt;
[[Arduino web controller]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 29.05.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20.06.2013]]&lt;br /&gt;
&lt;br /&gt;
[[Prova_pratica_21_01_15]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 17.06.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 - 25.09.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20/02/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Demone ruba input]]&lt;br /&gt;
&lt;br /&gt;
[[wifi daemon]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Problema Dei Filosofi]]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/portability.tgz portability.tgz]&lt;br /&gt;
&lt;br /&gt;
[[listx.h commentato + esempio su container_of]]&lt;br /&gt;
&lt;br /&gt;
[[Congettura di Goldbach]]&lt;br /&gt;
&lt;br /&gt;
[[list segments]]&lt;br /&gt;
&lt;br /&gt;
[[Execv/fork su file aperto]]&lt;br /&gt;
&lt;br /&gt;
[[Angry_Children]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 12/02/2009]]&lt;br /&gt;
&lt;br /&gt;
[[(Programma C) Un quadrato nella matrice]]&lt;br /&gt;
&lt;br /&gt;
[[&amp;quot;classi&amp;quot;_in_C]]&lt;br /&gt;
&lt;br /&gt;
[[Esempi del 02 dicembre 2014]]&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>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_2011.06.22&amp;diff=1013</id>
		<title>Prova Pratica 2011.06.22</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_2011.06.22&amp;diff=1013"/>
		<updated>2015-04-13T09:51:11Z</updated>

		<summary type="html">&lt;p&gt;MV: Created page with &amp;quot;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt; Scrivere uno script bash o un programma python che metta in ordine tutti i file di un sottoalbero dal piu' vecchio al piu' recente. La stampa finale deve ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere uno script bash o un programma python che metta in ordine tutti i file di un sottoalbero dal piu' vecchio al piu' recente.&lt;br /&gt;
La stampa finale deve mostrare solamente il path relativo dei file.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Soluzione di MV (bash)==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
SCRIPT=$0&lt;br /&gt;
&lt;br /&gt;
# il primo script è lanciato con 1 parametro: directory&lt;br /&gt;
# le chiamate ricorsive son fatte con 2 parametri: directory file&lt;br /&gt;
if (( $# &amp;lt; 1 ))&lt;br /&gt;
then&lt;br /&gt;
	echo &amp;quot;inserire il pathname di una directory come parametro&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ ! -d $1 ]&lt;br /&gt;
then&lt;br /&gt;
	echo &amp;quot;`pwd`/$1 non esiste o non è una directory&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
DIR=$1&lt;br /&gt;
&lt;br /&gt;
if (( $# == 2))&lt;br /&gt;
then&lt;br /&gt;
	FILE=$2		# gli script ricorsivi usano lo stesso file del chiamante&lt;br /&gt;
else&lt;br /&gt;
	FILE=tmp$$	# lo script iniziale crea un file temporaneo&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# salvo nel file temporaneo le informazioni che mi interessano di tutti i file&lt;br /&gt;
for i in `ls $DIR`	&lt;br /&gt;
do&lt;br /&gt;
	if [ -f $DIR/$i ]&lt;br /&gt;
	then&lt;br /&gt;
		stat -c &amp;quot;%y %n&amp;quot; $DIR/$i &amp;gt;&amp;gt; $FILE&lt;br /&gt;
	elif [ -d $DIR/$i ]&lt;br /&gt;
	then&lt;br /&gt;
		$SCRIPT $DIR/$i $FILE	# chiamata ricorsiva&lt;br /&gt;
	fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
# eseguito solo dal primo script (non da quelli ricorsivi)&lt;br /&gt;
if (( $# != 2))&lt;br /&gt;
then&lt;br /&gt;
	BEGIN=37	# indica il primo carattere da stampare per ogni riga&lt;br /&gt;
				# cioè tutti quelli prima indicano la data di modifica del file&lt;br /&gt;
	sort $FILE | cut --characters=&amp;quot;$BEGIN-&amp;quot;	# riordino per data e stampo il nome&lt;br /&gt;
	rm $FILE&lt;br /&gt;
fi&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Main_Page&amp;diff=897</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=897"/>
		<updated>2015-03-11T16:02:19Z</updated>

		<summary type="html">&lt;p&gt;MV: &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;
[[Esercizio 1, prova pratica 17.06.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1 - 25.09.2014]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 20/02/2014]]&lt;br /&gt;
&lt;br /&gt;
[[Demone ruba input]]&lt;br /&gt;
&lt;br /&gt;
[[wifi daemon]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 13/09/2013]]&lt;br /&gt;
&lt;br /&gt;
[[Problema Dei Filosofi]]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/portability.tgz portability.tgz]&lt;br /&gt;
&lt;br /&gt;
[[listx.h commentato + esempio su container_of]]&lt;br /&gt;
&lt;br /&gt;
[[Congettura di Goldbach]]&lt;br /&gt;
&lt;br /&gt;
[[list segments]]&lt;br /&gt;
&lt;br /&gt;
[[Execv/fork su file aperto]]&lt;br /&gt;
&lt;br /&gt;
[[Angry_Children]]&lt;br /&gt;
&lt;br /&gt;
[[Esercizio 1, prova pratica 12/02/2009]]&lt;br /&gt;
&lt;br /&gt;
[[(Programma C) Un quadrato nella matrice]]&lt;br /&gt;
&lt;br /&gt;
[[&amp;quot;classi&amp;quot;_in_C]]&lt;br /&gt;
&lt;br /&gt;
[[Esempi del 02 dicembre 2014]]&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>MV</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizio_1,_prova_pratica_17.06.2014&amp;diff=896</id>
		<title>Esercizio 1, prova pratica 17.06.2014</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizio_1,_prova_pratica_17.06.2014&amp;diff=896"/>
		<updated>2015-03-11T16:00:33Z</updated>

		<summary type="html">&lt;p&gt;MV: Created page with &amp;quot;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt; Occorre scrivere due programmi: mytar myuntar. Mytar prende come parametro il nome di una directory e il nome di un file: mytar ddd ddd.mytar mytar crea i...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Occorre scrivere due programmi: mytar myuntar.&lt;br /&gt;
Mytar prende come parametro il nome di una directory e il nome di un file:&lt;br /&gt;
mytar ddd ddd.mytar&lt;br /&gt;
mytar crea il file indicato come secondo parametro e registra in esso tutti i file regolari presenti nella directory (ddd&lt;br /&gt;
nell'esempio). Ogni file e' registrato nel secondo il seguente formato:&lt;br /&gt;
nome del file (stringa ASCII terminata da un byte 0)&lt;br /&gt;
lunghezza del file (stringa ASCII terminata da 0, la lunghezza e' registrata come stringa in rappresentazione in base 10&lt;br /&gt;
per non avere problemi di endianess e di ampiezza dei campi)&lt;br /&gt;
contenuto del file (un numero di byte corrispondente alla lunghezza indicata sopra).&lt;br /&gt;
Myuntar fa l'operazione inversa:&lt;br /&gt;
myuntar ddd.mytar newddd&lt;br /&gt;
crea la directory indicata come secondo parametro e, in essa, tutti i file registrati in ddd.mytar.&lt;br /&gt;
Per provare i due programmi, al termine dell'esecuzione di due comandi simili a quelli degli esempi mostrati qui sopra per&lt;br /&gt;
mytar e myuntar, tutti i file regolari presenti in ddd devono esistere in newddd e devono avere tutti lo stesso contenuto.&lt;br /&gt;
Se create una directory ddd contenente solo file regolare l'output di “diff -R ddd newddd” deve essere vuoto.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Soluzione di MV ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Per ora ho fatto solo la prima parte, cioè mytar.&lt;br /&gt;
L'unico problema che non riesco a capire è che entra in un loop infinito (scrivendo all'infinito sul file che crea!) se viene usato nella cartella dell'eseguibile stesso...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/*-------------------------------------MYTAR.C--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&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;errno.h&amp;gt;&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;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUF_DIM 512&lt;br /&gt;
&lt;br /&gt;
/* scrive nome, dimensione e contenuto del file indicato da src nel file dest (già aperto in scrittura) */&lt;br /&gt;
int filecpy(const char *src, const int dest, off_t size);&lt;br /&gt;
&lt;br /&gt;
/* ---------------------------------- MAIN ------------------------------- */&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{	&lt;br /&gt;
	DIR *ddd;&lt;br /&gt;
	int f;&lt;br /&gt;
	struct dirent *entry;&lt;br /&gt;
	struct stat dest_st;&lt;br /&gt;
	int e,i,len;&lt;br /&gt;
	char buf[BUF_DIM];&lt;br /&gt;
	&lt;br /&gt;
	if(argc != 3)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error: needed 2 parameters\n&amp;quot;);&lt;br /&gt;
		return 1;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	umask(0001);&lt;br /&gt;
	/* Creo il file passato come secondo parametro */&lt;br /&gt;
	if((f = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in open(): %s (%i)\n&amp;quot;,strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	/* Apro la directory passata come primo parametro, se c'è */&lt;br /&gt;
	if((ddd = opendir(argv[1])) == NULL)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in opendir(%s): %s (%i)\n&amp;quot;,argv[1],strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	/* mi sposto in quella directory */&lt;br /&gt;
	if(chdir(argv[1]) == -1)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in chdir(%s): %s (%i)\n&amp;quot;,argv[1],strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	e = errno;&lt;br /&gt;
	i = 0;	/* in i mantengo il numero totale di file copiati */&lt;br /&gt;
	/* leggo lo stat del file che ho creato */&lt;br /&gt;
	if(fstat(f, &amp;amp;dest_st) == -1)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in stat(%s): %s (%i)\n&amp;quot;,buf,strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	/* leggo le entry della directory finchè ce ne sono */&lt;br /&gt;
	while((entry = readdir(ddd)) != NULL)&lt;br /&gt;
	{&lt;br /&gt;
		struct stat st;&lt;br /&gt;
		&lt;br /&gt;
		strcpy(buf, entry-&amp;gt;d_name);&lt;br /&gt;
		&lt;br /&gt;
		if(stat(buf, &amp;amp;st) == -1)&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error in stat(%s): %s (%i)\n&amp;quot;,buf,strerror(errno),errno);&lt;br /&gt;
			return errno;&lt;br /&gt;
		}&lt;br /&gt;
		else if(st.st_mode &amp;amp; S_IFREG)	/* è un file */&lt;br /&gt;
		{	&lt;br /&gt;
			/* verifico che il file in questione sia diverso da quello aperto in scrittura, per evitare che scriva su se stesso all'infinito */&lt;br /&gt;
			if((st.st_ino == dest_st.st_ino) &amp;amp;&amp;amp; (st.st_rdev == dest_st.st_rdev))&lt;br /&gt;
				continue;&lt;br /&gt;
			&lt;br /&gt;
			if(filecpy(buf, f, st.st_size) == -1)&lt;br /&gt;
			{&lt;br /&gt;
				printf(&amp;quot;Error in filecpy(%s, %i)\n&amp;quot;,buf,f);&lt;br /&gt;
				return -1;&lt;br /&gt;
			}&lt;br /&gt;
			printf(&amp;quot;%s inserito.\n&amp;quot;, buf);&lt;br /&gt;
			i++;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if(e != errno)	/* sono uscito dal ciclo a causa di un errore */&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in readdir(): %s (%i)\n&amp;quot;,strerror(errno),errno);&lt;br /&gt;
		return errno;			&lt;br /&gt;
	}&lt;br /&gt;
	else	/* perchè ho visitato tutte le entrate della directory */&lt;br /&gt;
		printf(&amp;quot;end of directory, %i entry found.\n&amp;quot;, i);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int filecpy(const char *src, const int dest, off_t size)&lt;br /&gt;
{&lt;br /&gt;
	/* NB: dest è già aperto in scrittura */&lt;br /&gt;
	int s, len, tot;&lt;br /&gt;
	char buf[BUF_DIM];&lt;br /&gt;
	&lt;br /&gt;
	if((s = open(src,O_RDONLY,0)) == -1)	/* apro src in lettura */&lt;br /&gt;
		return -1;&lt;br /&gt;
	&lt;br /&gt;
	tot = write(dest, src, strlen(src)+1);	/* per prima cosa copio il titolo del file src */&lt;br /&gt;
							/* NB: faccio tot+1 per copiare anche lo 0 terminatore */&lt;br /&gt;
	sprintf(buf, &amp;quot;%i&amp;quot;, (int)size);	/* poi copio la dimensione */&lt;br /&gt;
	tot += write(dest, buf, strlen(buf)+1);&lt;br /&gt;
	&lt;br /&gt;
	/* infine copio tutto il contenuto */&lt;br /&gt;
	while( (len = read(s,buf,BUF_DIM)) != 0)&lt;br /&gt;
	{&lt;br /&gt;
		if(len == -1)&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error in read(): %s (%i)\n&amp;quot;,strerror(errno),errno);&lt;br /&gt;
			return -1;&lt;br /&gt;
		}&lt;br /&gt;
		/*else printf(&amp;quot;%i\n&amp;quot;,len);*/&lt;br /&gt;
		tot += write(dest, buf, len);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	return tot;	/* restituisce il numero totale di byte scritti */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>MV</name></author>
	</entry>
</feed>