/******************************************************************************* * * Este programa faz parte do curso sobre tempo real do Laboratorio Embry-Riddle * * Seguem os comentarios 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: * * Propsito: O propsito 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 /* for gettimeofday() */ #include /* for gettimeofday() */ #include /* for printf() */ #include /* for fork() */ #include /* for wait(), msgget(), msgctl() */ #include /* for wait() */ #include /* for msgget(), msgctl() */ #include /* for msgget(), msgctl() */ /* * 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 /* * 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 1234 #define MESSAGE_QUEUE_ID_ 2345 /* * Constantes */ #define SENDER_DELAY_TIME 20 #define MESSAGE_MTYPE 1 /* * A estrutura de dados seguinte contera os dados que serao transferidos * pela fila. Pode conter um numero de mensagem (msg_no) e o tempo de envio * (send_time). Para filas de mensagens, esta estrutura pode conter * qualquer dado que seja necessario. */ typedef struct { unsigned int msg_no; struct timeval send_time; char *tamanho_adcional; } data_t; /* Estrutura que contem matriz de dados medidos na transferencia da mensagem */ typedef struct{ unsigned long timeofsend[NO_OF_ITERATIONS]; unsigned long timeofreceive[NO_OF_ITERATIONS]; } timeForPai; /* numero da fila de transferencia da matriz */ int queue_id_; /* * O conteudo da estrutura de dados seguinte sera enviado atraves da fila de * mensagens. A estrutura contem dois dados. O primeiro e o tipo da * mensagem (mtype) que sera uma identificacao de mensagem. Para este * experimento este sera sempre o mesmo. O segundo e uma matriz com tamanho * igual a estrutura declarada anteriormente. Nessa matriz e que o dados * a serem transferidos serao colocados. Sob a maioria das circunstancias, * esta estrutura nao necessita mudar. */ typedef struct { long mtype; char mtext[sizeof(data_t)]; } msgbuf_t; typedef struct { long mtype; char mtext[sizeof(timeForPai)]; } msgbuf_t_; /* * Filhos */ void Receiver(int queue_id); void Sender(int queue_id); void SenderMatriz(int queue_id_,msgbuf_t_ message_buffer,timeForPai *matriz); /* * Programa principal */ int main( int argc, char *argv[] ) { /* * Algumas variaveis necessarias */ int rtn; int count; float delta=0,delta2=0; float max=0; float total=0, total2=0; /* * Variaveis relativas a fila, id e key */ int queue_id; key_t key = MESSAGE_QUEUE_ID; /* * 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 ) { fprintf(stderr,"Impossivel criar a fila de mensagens!\n"); exit(1); } /* fila pra receber os dados da matriz */ key_t key_ = MESSAGE_QUEUE_ID_; if( (queue_id_ = msgget(key_, IPC_CREAT | 0666)) == -1 ) { fprintf(stderr,"Impossivel criar a fila de mensagens 2!\n"); exit(1); } /* * Segundo, inicializa dois filhos * * OBS: Lembre-se, os filhos herdarao a informacao sobre a fila * estabelecida no pai! */ rtn = 1; for( count = 0; count < 2; count++ ) { if( rtn != 0 ) { rtn = fork(); } else { break; } } /* * Verifica o valor retornado para determinar se o processo e 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("\n############## Exemplo 3 - Modificado ###############\n\n"); printf("Receptor iniciado ...\n"); Receiver(queue_id); exit(0); } else if( rtn == 0 && count == 2 ) { /* * 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 */ wait(NULL); wait(NULL); /* Recebo os resultados de tempo do filho */ msgbuf_t_ message_buffer; timeForPai *matriz = (timeForPai *)(message_buffer.mtext); if( msgrcv(queue_id_,(struct msgbuf *)&message_buffer,sizeof(timeForPai),MESSAGE_MTYPE,0) == -1 ) { fprintf(stderr, "Impossivel receber mensagem!\n"); exit(1); } int i; for(i=0;i>>> %d + %d ",matriz->timeofreceive[i],matriz->timeofsend[i]); delta = (matriz->timeofreceive[i] - matriz->timeofsend[i])/(float)MICRO_PER_SECOND; delta += (matriz->timeofreceive[i] - matriz->timeofsend[i])/(float)MICRO_PER_SECOND; total += delta; delta2 = (matriz->timeofreceive[i] - matriz->timeofsend[i]); delta2 += (matriz->timeofreceive[i] - matriz->timeofsend[i]); total2 += delta2; // tempo maximo if( delta > max ) { max = delta; } } /* * Exibe os resultados */ printf("\n\n=================transferencia==================="); printf("\nTempo medio [Segundos: %.10f ] - [MicroSegundos: %f ]", total / NO_OF_ITERATIONS, total2 / NO_OF_ITERATIONS); printf("\nTempo maximo [Segundos: %.10f ] - [MicroSegundos: %f ]\n\n", max, max * (float)MICRO_PER_SECOND); if( msgctl(queue_id,IPC_RMID,NULL) != 0 ) { fprintf(stderr,"Impossivel remover a fila!\n"); exit(1); } if( msgctl(queue_id_,IPC_RMID,NULL) != 0 ) { fprintf(stderr,"Impossivel remover a fila!\n"); exit(1); } exit(0); } } /* * Esta funcao recebe as mensagens */ void Receiver(int queue_id) { /* * Variaveis locais */ int count; struct timeval receive_time; float delta; float max; float total = 0; /* * Este e o buffer para receber a mensagem */ msgbuf_t message_buffer; msgbuf_t_ message_buffer_; timeForPai *matriz = (timeForPai *)(message_buffer_.mtext); message_buffer.mtype = MESSAGE_MTYPE; /* * 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++ ) { /* * 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); } /* * Chama gettimeofday() */ gettimeofday(&receive_time,NULL); /* armazena os dados na matriz */ matriz->timeofsend[count] = data_ptr->send_time.tv_usec; matriz->timeofreceive[count] = receive_time.tv_usec; //printf("\nmatriz >>>> %d : %d + %d", count,matriz->timeofsend[count],matriz->timeofreceive[count]); } /* Envia resultados para o pai */ SenderMatriz(queue_id_,message_buffer_,matriz); return; } /* * Esta funcao envia mensagens */ void Sender(int queue_id) { /* * Variaveis locais */ int count,n; struct timeval send_time; /* tamanho a aumentar na mensagem * se eu criar uma variavel com tamanho X, e realocar N posicoes, eu terei N bytes a mais * com essa ideia que eu realoco o tamanho da mensagem */ while(1) { printf("\tTamanho a alocar [*100]: "); scanf("%d",&n); if(n%100 == 0) break; } /* * 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; data_ptr->tamanho_adcional = (char*) malloc (n*sizeof(char)); /* * 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 para permitir ao receptor ser * executado */ usleep(SENDER_DELAY_TIME); } return; } /* Essa funcao envia mensagens para o pai, com a matrizes dos resultados */ void SenderMatriz(int queue_id,msgbuf_t_ message_buffer,timeForPai *matriz) { /* Testa se ta chegando os resultados aqui int j; for(j=0;jtimeofsend[j],matriz->timeofreceive[j]); */ message_buffer.mtype = MESSAGE_MTYPE; /* * 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(timeForPai),0) == -1 ) { fprintf(stderr, "Impossivel enviar mensagem!\n"); exit(1); } /* * Dorme por um curto espaco de tempo para permitir ao receptor ser * executado */ sleep(SENDER_DELAY_TIME); return; }