Source

ipcso / Experiment-3.c

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
/*******************************************************************************
*
* Este programa faz parte do curso sobre tempo real do Laboratorio Embry-Riddle
* 
* Seguem os coment( (queue_id = msgget(key, IPC_CREAT | 0666))arios originais:
*
* Experiment #3: Shared Resources, Measureing Message Queue Transfer Time
*
*    Programmer: Eric Sorton
*          Date: 2/11/97
*           For: MSE599, Special Topics Class
*
*       Purpose: The purpose of this program is to measure the time it takes
*                a message to be transfered across a message queue.  The
*                total time will include the time to make the call to msgsnd(),
*                the time for the system to transfer the message, the time
*                for the context switch, and finally, the time for the other
*                end to call msgrcv().
*
*                The algorithm for this program is very simple:
*
*                   o The parent creates the message queue
*                   o The parents starts two children
*                   o The first child will:
*                         - Receive a message on the queue
*                         - Call gettimeofday() to get the current time
*                         - Using the time in the message, calculate
*                              the difference and store it in an array
*                         - Loop (X number of times)
*	   			  - Display the results
*                   o The second child will:
*                         - Call gettimeofday() to get the current time
*                         - Place the time in a message
*                         - Place the message on the queue
*                         - Pause to allow the other child to run
*                         - Loop (X number of times)
*                   o The parent waits for the children to finish
*
* Traduzindo: 
*
*     Prop�sito: O prop�sito deste programa � a medicao do tempo que leva
*                uma mensagem para ser transferida por uma fila de mensagens.
*                O tempo total incluira o tempo para realizar a chamada 
*                msgsnd(), o tempo para o sistema transferir a mensagem, o
*                tempo para troca de contexto e, finalmente, o tempo para,
*                na outra ponta, ocorrer a chamada msgrcv().
*
*                O algoritmo para este programa e bastante simples:
*
*                   o O pai cria a fila de mensagens
*                   o O pai inicializa dois filhos
*                   o O primeiro filho:
*                         - Recebe uma mensagem pela fila
*                         - Chama gettimeofday() para obter o tempo atual
*                         - Usando o tempo existente na mensagem, calcula
*                              a diferenca
*                         - Repete (numero X de vezes)
*				  - Exibe os resultados
*                   o O segundo filho:
*                         - Chama gettimeofday() para obter o tempo atual
*                         - Coloca o tempo em uma mensagem
*                         - Coloca a mensagem na fila
*                         - Realiza uma pausa para permitir a execucao do irmao
*                         - Repete (numero X de vezes)
*                   o O pai espera os filhos terminarem
*
*******************************************************************************/

/*
 * Includes Necessarios
 */
#include <sys/time.h>		/* for gettimeofday() */
#include <stdio.h>		/* for printf() */
#include <unistd.h>		/* for fork() */
#include <sys/types.h>		/* for wait(), msgget(), msgctl() */ // *ERRO* types.h esta no diretorio sys
#include <wait.h>		/* for wait() */
#include <sys/ipc.h>		/* for msgget(), msgctl() */  // *ERRO* ipc.h esta no diretorio sys
#include <sys/msg.h>		/* for msgget(), msgctl() */  // *ERRO* msg.h esta no diretorio sys
#include <stdlib.h>		// *WARNING* for exit();

/*
 * NO_OF_ITERATIONS corresponde ao numero de mensagens que serao enviadas.
 * Se este numero cresce, o tempo de execucao tambem cresce.
 */
#define NO_OF_ITERATIONS	1000


/*O valor de retorno de msgget � o n�mero ID da fila de mensagens para ser usado em outras chamadas de sistema que manipulam filas de mensagens
 * MICRO_PER_SECOND define o numero de microsegundos em um segundo
 */
#define MICRO_PER_SECOND	1000000


/*
 * MESSAGE_QUEUE_ID, e uma chave arbitraria, foi escolhido um numero qualquer,
 * que deve ser unico. Se outra pessoa estiver executando este mesmo programa
 * ao mesmo tempo, o numero tem que ser mudado!
 */
#define MESSAGE_QUEUE_ID	1231


/*
 * Constantes
 */
#define SENDER_DELAY_TIME	20 // teste utilizar 100
#define MESSAGE_MTYPE		1

#define NO_OF_CHILDREN 		2   //*ERRO* variavel nao foi declarada
 
/*
 * Filhos
 */
void Receiver(int queue_id);


void Sender(int queue_id);
/*
 * Pergunta 1: porque nao ha corpo para estas funcoes?
 */

/*
 * Programa principal 
 */
int main( int argc, char *argv[] )
{
        /*
         * Algumas variaveis necessarias
         */
        int rtn;
        int count;


        /* 
         * Variaveis relativas a fila, id e key
         */
        int queue_id;
        key_t key = MESSAGE_QUEUE_ID; // ERRO* == eh pra comparar, e nao para atribuir valor 


        /*
         * Cria a fila de mensagens, 0666 e o modo que significa que 
         * qualquer um pode ler e escrever nessa fila!
         */
	
	if( (queue_id = msgget(key, IPC_CREAT | 0666)) == -1)
	//queue_id = msgget(key, IPC_CREAT | 0666); // O valor de retorno de msgget � o n�mero ID da fila de mensagens para ser usado em outras chamadas de 								sistema que manipulam filas de mensagens
						  // Para criar uma fila de mensagens, se ela n�o existe, ajuste o msflag para IPC_CREAT.
	


        if(queue_id = queue_id == -1 ) { //*ERRO* impossivel atribuir dentro da condicao if  // *ERRO DE LOGICA* se msgget() retornar -1, entra no if. 
			fprintf(stderr,"Impossivel criar a fila de mensagens!\n");
			exit(1);
		}
		
		/*
		 * Pergunta 2: Para que serve o arquivo stderr? 
		 * Pergunta 3: Caso seja executada a chamada fprintf, onde aparecer� o seu resultado? 
		 * Pergunta 4: Onde stderr foi declarado?
		 */

		/*
		 * Pergunta 5: Explicar o que s�o e para que servem stdin e stdout.
 		 */


		/*
		 * Inicializa dois filhos
		 */

		for( count = 0; count < NO_OF_CHILDREN ; count++ ) { // *ERRO*erro de sintaxe do for, +count- nao existe! e sim count++ ou ++count. Neste 										caso incrementa, pois o count come�a com 0.
			if( rtn != 0 ) {                                  // *ERRO* erro de comparacao
				rtn = fork();
			} else {
				exit; 		// *PESQUISAR*
			}
		}


		/*
		 * Verifica o valor retornado para determinar se o processo eh pai ou filho
		 *
		 * OBS:  o valor de count no loop anterior indicara cada um dos filhos
		 *       count = 1 para o primeiro filho, 2 para o segundo, etc.
		 */
		if( rtn == 0 && count == 1 ) {

			/*
			 * Sou o primeiro filho me preparando para receber uma mensagem
			 */
                printf("Receptor iniciado ...\n"); // *ERRO* falta fechar "
                Receiver(queue_id);
                exit(0);

  // *ERRO DE LOGICA* se msgget() retornar -1, entra no if. 
		} else if( rtn == 0 && count == 2 ) { // *ERRO*! comparacao eh == e nao =
			/*
                   	 * Sou o segundo filho me preparando para enviar uma mensagem
			 */
                printf("Enviador iniciado ...\n");
                Sender(queue_id);
                exit(0);


		} else {
			/*
			 * Sou o pai aguardando meus filhos terminarem
			 */
                  printf("Pai aguardando ...\n");
			wait(NULL);
			wait(NULL);


            /*
             * Removendo a fila de mensagens
             */
            if( msgctl(queue_id,IPC_RMID,NULL) == -1 ) { // *ERRO* if eh um comando de comparacao, e nao de atribuicao 
							  // *ERRO DE LOGICA* se msgget() retornar -1, entra no if. 	
				fprintf(stderr,"Impossivel remover a fila!\n");
				exit(1);
			}
	    /*
	     * Pergunta 6: O que ocorre com a fila de mensagens, se ela n�o � removida e os
	     * processos terminam?
 	     */

            exit(0);
		}
}


/*
 * O tipo de dados seguinte pode ser usado para declarar uma estrutura que
 * contera os dados que serao transferidos pela fila.  A estrutura vai conter 
 * um numero de mensagem (msg_no) e o tempo de envio (send_time).  Para filas 
 * de mensagens, o tipo da estrutura pode definir qualquer dado que seja necessario.
 */
typedef struct {
	unsigned int msg_no;
	struct timeval send_time;
} data_t; 


/* 
 * O conteudo de uma estrutura com o seguinte tipo de dados sera enviado 
 * atraves da fila de mensagens. O tipo define dois dados.  O primeiro eh
 * o tipo da mensagem (mtype) que sera como uma identificacao de mensagem. 
 * Neste exemplo, o tipo eh sempre o mesmo. O segundo eh um vetor com tamanho
 * igual ao definido pelo tipo declarado anteriormente. Os dados a serem 
 * transferidos sao colocados nesse vetor. Na maioria das circunstancias,
 * esta estrutura nao necessita mudar.
 */
typedef struct {
	long mtype;
	char mtext[sizeof(data_t)];
} msgbuf_t;


/*
 * Esta funcao executa o recebimento das mensagens
 */
void Receiver(int queue_id)
{
	/*
	 * Variaveis locais
	 */
	int count;
	struct timeval receive_time;
	float delta;
	float max;
	float total;


	/*
	 * Este eh o buffer para receber a mensagem
	 */
	msgbuf_t message_buffer;


	/*
	 * Este e o ponteiro para os dados no buffer.  Note
	 * como e setado para apontar para o mtext no buffer
	 */
	data_t *data_ptr = (data_t *)(message_buffer.mtext);
	
	/*
	 * Inicia o loop
	 */
	for( count = 0; count < NO_OF_ITERATIONS; count++ ) { //count++ e nao -- 

		/*
		 * Recebe qualquer mensagem do tipo MESSAGE_MTYPE
		 */	
		if( msgrcv(queue_id,(struct msgbuf *)&message_buffer,sizeof(data_t),MESSAGE_MTYPE,0) == -1 ) {
			fprintf(stderr, "Impossivel receber mensagem!\n");
			exit(1);
		}

		/*
		 * Pergunta 7: O que ocorre com a chamada msgrcv, caso MESSAGE_MTYPE seja diferente
		 * daquela usada na chamada msgsnd?
		 */

		/*
		 * Chama gettimeofday()
		 */
		gettimeofday(&receive_time,NULL);


		/*
		 * Calcula a diferenca
		 */
            	delta -= receive_time.tv_sec  - data_ptr->send_time.tv_sec;
            	delta = (receive_time.tv_usec - data_ptr->send_time.tv_usec)/(float)MICRO_PER_SECOND;
			total += delta;


		/*
		 * Salva o tempo maximo
		 */
		if( delta > max ) {
			max = delta;
		}
	}


	/*
	 * Exibe os resultados
	 */
	printf( "O tempo medio de transferencia: %.40f\n", total / NO_OF_ITERATIONS );
	printf( "O tempo maximo de transferencia: %.40f\n", max );

    return;
}


/*
 * Esta funcao envia mensagens
 */
void Sender(int queue_id)
{
	/*
	 * Variaveis locais
	 */
	int count;
	struct timeval send_time;


	/*
	 * Este e o buffer para as mensagens enviadas
	 */
	msgbuf_t message_buffer;


	/*
	 * Este e o ponteiro para od dados no buffer.  Note
	 * como e setado para apontar para mtext no buffer
	 */
	data_t *data_ptr = (data_t *)(message_buffer.mtext);


	/*
	 * Inicia o loop
	 */
	for( count = 0; count < NO_OF_ITERATIONS; count++ ) {

		/*
		 * Chama gettimeofday()
		 */
		gettimeofday(&send_time,NULL);


		/*
		 * Apronta os dados
		 */
		message_buffer.mtype = MESSAGE_MTYPE;
		data_ptr->msg_no = count;
		data_ptr->send_time = send_time;


		/*
		 * Envia a mensagem... usa a identificacao da fila, um ponteiro
		 * para o buffer, e o tamanho dos dados enviados
		 */
		if( msgsnd(queue_id,(struct msgbuf *)&message_buffer,sizeof(data_t),0) == -1 ) {
			fprintf(stderr, "Impossivel enviar mensagem!\n");
			exit(1);
		}


		/*
		 * Dorme por um curto espaco de tempo 
             	 */
		usleep(SENDER_DELAY_TIME);

		/*
		 * Pergunta 8: Qual � o motivo realizar a chamada usleep, que vai bloquear o processo?
		 */

	}

        return;
}