1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Problema em C (utilizando semáforos e memória partilhada em ambiente linux )

Discussão em 'Programação' iniciada por Roberto_TGEI09, 25 de Junho de 2012. (Respostas: 0; Visualizações: 1594)

  1. Roberto_TGEI09

    Roberto_TGEI09 Power Member

    boas,

    como descrevi no titulo estou com um problema em C, estou a criar um programa para a troca de mensagens entre um cliente e um servidor, em ambiente linux. Para isso tenho que utilizar semáforos e memória partilhada para as trocas de mensagens. o meu problema é que supostamente tenho o sistema de semáforos bem implementado, mas o cliente fica bloqueado ao tentar utilizar alguma das opções do menu... O servidor faz as suas operações, troca as mensagens e liberta os semáforos e do lado do cliente fica bloqueado.

    Cliente:

    Código:
    /* Cliente */#include <sys/sem.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    #include <unistd.h>
    #include <stdio_ext.h>
    #include <sys/types.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdio_ext.h>
    #include <sys/msg.h>
    
    
    #define EXIT_FAILURE -1
    #define EXIT_SUCCESS  0
    
    
    #define DEBUG
    
    
    /* Definicao da estrutura das mensagens */
    struct mensagem {
        int tipo;
        int semID;
        int shmID;
        char texto[256];
    };
    
    
    /* Definicao da Estrutura aluno */
    struct livro {
        int numero;
        char titulo[30];
        char tipo[30];
        char autor[30];
        char editora[30];
    };
    
    
    /* Definir semun caso n√£o esteja definida */
    #ifdef _SEM_SEMUN_UNDEFINED
    #undef _SEM_SEMUN_UNDEFINED
    union semun {
        int val;
        struct semid_ds *buf;
        unsigned short int *array;
        struct seminfo *__buf;
    };
    #endif
    
    
    /* Definir as operações sobre os semáforos */
    struct sembuf UP = {0, 1, 0};
    struct sembuf DOWN = {0, -1, 0};
    
    
    
    
    int menu() {
    
    
        int i; 
    
    
        printf ("\n-------------------- MENU BIBLIOTECA-------------------------|\n");
        printf ("       1 - Inserir Livros\n");                               
        printf ("       2 - Remover Livros\n");
        printf ("       3 - Listar Livros\n");
        printf ("       0 - Sair\n");
        printf ("\n---------------------------------------------------------|\n");
        printf ("\n Qual a sua opcao ? ");
    
    
        __fpurge(stdin);
        scanf("%d", &i);
    
    
        return i;     
    }
    
    
    
    
    int main(int argc, char *argv[]) {
    
    
        key_t chave;
        int filaID, i, n;
        struct mensagem msg;
        int semID, shmID;
        struct livro *shmptr;
        char buffer[31];
        union semun semopts;
    
    
        if (argc != 2) {
            printf ("\nArgumentos incorretos ! Deve chamar o programa com o seu nome e o ID do cliente (Ex: cliente 1)\n");
            return EXIT_FAILURE;
        }
    
    
        chave = ftok(".",'a');
    
    
        /* Associar fila de mensagens */
        filaID = msgget( chave, IPC_CREAT | 0666 );
        if ( filaID == -1) {
            printf("Erro na associacao da fila de mensagens - Problema com o SERVIDOR\n");
            return EXIT_FAILURE;
        }
        else printf ("\nID Fila=%d\n", filaID);
        
        chave = ftok(".",argv[1][0]);
    
    
        /* Criar um grupo com 1 sem√°foro */
        semID = semget(chave, 1, 0666 | IPC_CREAT);
        if (semID == -1) {
            printf("Erro na criacao do Semaforo\n");
            return -1;
        }
        #ifdef DEBUG
        else printf ("\nID Semaforo=%d\n", semID);
        #endif
    
    
        /* Inicializar o semaforo a 0 */
        semopts.val = 0;
        semctl(semID, 0, SETVAL, semopts);
    
    
        /* Criação do bloco de memória partilhada */
        shmID = shmget(chave, sizeof(struct livro), IPC_CREAT | 0666);
        if (shmID == -1) {
            printf("Erro na criacao do bloco de mem. partilhada\n");
            return -1;
        }
        #ifdef DEBUG
        else printf ("\nID Memoria=%d\n", shmID); 
        #endif
    
    
        do {
            i = menu();
    
    
            switch (i) {
                case 1 : shmptr = shmat(shmID, NULL, 0); /* Attach */
                         if ((int)shmptr != -1) {   
    
    
                             /* Pedir os dados ao utilizador */
    
    
                             printf("Titulo: ");
                             __fpurge(stdin);
                             memset(buffer, 0, 30);
                             fgets(buffer, 30, stdin);
                             buffer[strlen(buffer)-1] = '\0';
                             strcpy(shmptr->titulo, buffer);
    
    
                             printf("Tipo: ");
                             __fpurge(stdin);
                             memset(buffer, 0, 30);
                             fgets(buffer, 30, stdin);
                             buffer[strlen(buffer)-1] = '\0';
                             strcpy(shmptr->tipo, buffer);
    
    
                             printf("Autor: ");
                             __fpurge(stdin);
                             memset(buffer, 0, 30);
                             fgets(buffer, 30, stdin);
                             buffer[strlen(buffer)-1] = '\0';
                             strcpy(shmptr->autor, buffer);
    
    
                             printf("Editora: ");
                             __fpurge(stdin);
                             memset(buffer, 0, 30);
                             fgets(buffer, 30, stdin);
                             buffer[strlen(buffer)-1] = '\0';
                             strcpy(shmptr->editora, buffer);
    
    
                 shmdt(shmptr); /* Dettach */
                 
                             /* Enviar Mensagem com pedido ao Servidor */
                             msg.tipo = 1;
                             msg.semID = semID;
                             msg.shmID = shmID;
                             if ( msgsnd( filaID, &msg, sizeof(msg), 0) == 0 ) {
                                 printf("\nPedido enviado com sucesso\n");
                             }
                             else {
                                 printf("Erro no envio da mensagem\n");
                                 return EXIT_FAILURE;
                             }
    
    
                             semop(semID, &DOWN, 1);  /* Esperar a resposta no servidor */
    
    
                             /* Receber mensagem */
                             if ( msgrcv(filaID, &msg, sizeof(msg), 0, 0) < 0 ) {
                                 printf("Erro a receber a mensagem\n");
                                 return EXIT_FAILURE;
                             }
    
    
                             switch(msg.tipo) {
                                 case 13: printf("Pedido executado com sucesso\n");
                                          break;
                             };
                 
                         }
                         else { 
                             printf ("\nErro na associacao a memoria !\n");
                             __fpurge (stdin);
                             getchar();
                         };
                         break;
    
    
            case 2 : shmptr = shmat(shmID, NULL, 0); /* Attach */
                         if ((int)shmptr != -1) {   
    
    
                             /* Pedir os dados ao utilizador */
    
    
                             printf("Numero: ");
                             __fpurge(stdin);
                             scanf("%d", &shmptr->numero);
    
    
                             /* Enviar Mensagem com pedido ao Servidor */
                             msg.tipo = 2;
                             msg.semID = semID;
                             msg.shmID = shmID;
                             if ( msgsnd( filaID, &msg, sizeof(msg), 0) == 0 ) {
                                 printf("\nPedido enviado com sucesso\n");
                             }
                             else {
                                 printf("Erro no envio da mensagem\n");
                                 return EXIT_FAILURE;
                             }
                             semop(semID, &DOWN, 1);  /* Esperar a resposta no servidor */
                             
                             /* Receber mensagem */
                             if ( msgrcv(filaID, &msg, sizeof(msg), 0, 0) < 0 ) {
                                 printf("Erro a receber a mensagem\n");
                                 return EXIT_FAILURE;
                             }
    
    
                             switch(msg.tipo) {
                                 case 13: printf("Pedido executado com sucesso\n");
                                          break;
                             };
                             shmdt(shmptr); /* Dettach */ 
    
    
                         }
                         else { 
                             printf ("\nErro na associacao a memoria !\n");
                             __fpurge (stdin);
                             getchar();
                         };
                         break;
                 
            case 3 : shmptr = shmat(shmID, NULL, 0); /* Attach */
                         if ((int)shmptr != -1) {   
    
    
                             /* Pedir os dados ao utilizador */
    
    
                             printf("Numero: ");
                             __fpurge(stdin);
                             scanf("%d", &shmptr->numero);
    
    
                             /* Enviar Mensagem com pedido ao Servidor */
                             msg.tipo = 3;
                             msg.semID = semID;
                             msg.shmID = shmID;
                             if ( msgsnd( filaID, &msg, sizeof(msg), 0) == 0 ) {
                                 printf("\nPedido enviado com sucesso\n");
                             }
                             else {
                                 printf("Erro no envio da mensagem\n");
                                 return EXIT_FAILURE;
                             }
                             semop(semID, &DOWN, 1);  /* Esperar a resposta no servidor */
                             
                             /* Receber mensagem */
                             if ( msgrcv(filaID, &msg, sizeof(msg), 0, 0) < 0 ) {
                                 printf("Erro a receber a mensagem\n");
                                 return EXIT_FAILURE;
                             }
    
    
                             switch(msg.tipo) {
                                 case 13: printf("Pedido executado com sucesso\n");
                                          break;
                             };
                             shmdt(shmptr); /* Dettach */ 
    
    
                         }
                         else { 
                             printf ("\nErro na associacao a memoria !\n");
                             __fpurge (stdin);
                             getchar();
                         };
                         break;         
                 
                 
            case 0 :     
                         semctl(semID, 0, IPC_RMID);              /* Apagar Semaforo */
                         #ifdef DEBUG
                            printf ("Apaguei Semaforo !\n");
                         #endif
    
    
                         shmctl(shmID, 0, IPC_RMID);              /* Apagar Memoria */
                         #ifdef DEBUG
                            printf ("Apaguei Memoria Partilhada !\n");
                         #endif
    
    
                 /* Remover a fila */
                 msgctl(filaID, IPC_RMID, NULL);    
                 #ifdef DEBUG
                printf ("Apaguei a Fila de Mensagens !\n");
                 #endif
        
                         break;
            };
    
    
        } while (i != 0);
    
    
        return EXIT_SUCCESS;
    }
    
    
    


    Servidor:

    Código:
    /* server.c - Servidor */#include <sys/sem.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    #include <unistd.h>
    #include <stdio_ext.h>
    #include <sys/types.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdio_ext.h>
    #include <sys/msg.h>
    #include <stdlib.h>
    
    
    /* Descomentar para ativar as mensagens de debug */
    #define DEBUG
    
    
    
    
    /* Definicao da estrutura das mensagens */
    struct mensagem {
        int tipo;
        int semID;
        int shmID;
        char texto[256];
    };
    
    
    /* Definicao da Estrutura aluno */
    struct livro {
        int numero;
        char titulo[30];
        char tipo[30];
        char autor[30];
        char editora[30];
    };
    
    
    /* Definir semun caso n√£o esteja definida */
    #ifdef _SEM_SEMUN_UNDEFINED
    #undef _SEM_SEMUN_UNDEFINED
    union semun {
        int val;
        struct semid_ds *buf;
        unsigned short int *array;
        struct seminfo *__buf;
    };
    #endif
    
    
    /* Definir as operações sobre os semáforos */
    struct sembuf UP = {0, 1, 0};
    struct sembuf DOWN = {0, -1, 0};
    
    
    int main() {
        key_t chave;
        int filaID;
        struct mensagem msg;
        int semID, shmID;
        struct livro *shmptr, tmpLivro;
        FILE *fp = NULL, *tmpFile = NULL;
        int livroID, lastID = 0;
        char line[130];
    
    
        
        if ((fp = fopen("livros.csv", "r")) == NULL) {
            printf("Nao foi possivel abrir a BD.\n");
        return EXIT_FAILURE;
        }
    
    
        while(fgets(line, 129, fp) != NULL)
        lastID++;
        
        fclose(fp);
        
        chave = ftok(".",'a');
    
    
        /* Criar / associar fila de mensagens */
        filaID = msgget( chave, IPC_CREAT | 0666 );
        if ( filaID == -1) {
            printf("Erro na criacao da fila de mensagens\n");
            return EXIT_FAILURE;
        }
        else printf ("\nID Fila=%d\n", filaID);
    
    
        do {
            /* Receber mensagem */
            if ( msgrcv( filaID, &msg, sizeof(msg), 0, 0) < 0 ) {
                printf("Erro a receber a mensagem\n");
                return EXIT_FAILURE;
            }
    
    
    #ifdef DEBUG
            printf ("\nRecebi Msg. Tipo=%d", msg.tipo);
    #endif
        
            switch (msg.tipo) {
                case 1 :
    #ifdef DEBUG
                    printf ("\nRecebi um pedido de insercao (SemID=%d, Shm=%d)", msg.semID, msg.shmID);
    #endif
                    shmptr = shmat(msg.shmID, NULL, 0); /* Attach */
    
    
                    if ((int)shmptr != -1) {   
    
    
    #ifdef DEBUG
                        /* Mostrar o elemento que vem na memória partilhada */
                        printf ("\nElemento a Inserir: Titulo=%s, Tipo=%s, Autor=%s, Editora=%s\n", shmptr->titulo, shmptr->tipo, shmptr->autor, shmptr->editora);
    #endif
                        if ((fp = fopen("livros.csv", "a")) == NULL) {
                            printf("Nao foi possivel abrir a BD.\n");
                            return EXIT_FAILURE;
                        }
    
    
                        fprintf(fp, "%s;%s;%s;%s\n", shmptr->titulo, shmptr->tipo, shmptr->autor, shmptr->editora);
                        fclose(fp);
    
    
                shmdt(shmptr);     /* Detach */            
                
    #ifdef DEBUG
                        printf ("Vou desbloquear o semaforo %d\n", msg.semID);
    #endif
                semop(msg.semID, &UP, 1); /* Desbloquear Cliente no Semaforo */  
                        
                /* Enviar Mensagem com resposta de sucesso ao Cliente */
                        msg.tipo = 13;
    
    
                        if ( msgsnd(filaID, &msg, sizeof(msg), 0) == 0 ) {
                            printf("Pedido executado com sucesso\n");
                        }
                        else {
                            printf("Erro no envio da mensagem\n");
                            return EXIT_FAILURE;
                        }
                    
                    }                        
                    break;
    
    
            case 2 :
    #ifdef DEBUG
                    printf ("\nRecebi um pedido de remocao (SemID=%d, Shm=%d)", msg.semID, msg.shmID);
    #endif
                    shmptr = shmat(msg.shmID, NULL, 0); /* Attach */
    
    
                    if ((int)shmptr != -1) {   
    
    
    #ifdef DEBUG
                        /* Mostrar o elemento que vem na memória partilhada */
                        printf ("\nElemento a remover: Numero=%d\n", shmptr->numero);
    #endif
                
                        if ((fp = fopen("livros.csv", "r")) == NULL) {
                            printf("Nao foi possivel abrir a BD.\n");
                            return EXIT_FAILURE;
                        }
                        
                        if ((tmpFile = fopen("livros.csv.tmp", "w")) == NULL) {
                            printf("Nao foi possivel criar o ficheiro temporario.\n");
                            return EXIT_FAILURE;
                        }
    
    
                        for(int i = 0; fgets(line, 129, fp) != NULL; i++) {
                if(i == shmptr->numero)
                    continue;
                else fputs(line, tmpFile);
                }
                
                        fclose(fp);
                fclose(tmpFile);
                
                system("mv livros.csv.tmp livros.csv");
                        shmdt(shmptr);     /* Detach */
    #ifdef DEBUG
                        printf ("Vou desbloquear o semaforo %d\n", msg.semID);
    #endif
    
    
                semop(msg.semID, &UP, 1); /* Desbloquear Cliente no Semaforo */
                        
                /* Enviar Mensagem com resposta de sucesso ao Cliente */
                        msg.tipo = 13;
    
    
                        if ( msgsnd(filaID, &msg, sizeof(msg), 0) == 0 ) {
                            printf("Pedido executado com sucesso\n");
                        }
                        else {
                            printf("Erro no envio da mensagem\n");
                            return EXIT_FAILURE;
                        }                  
                    }                        
                    break;
    
    
            case 3 :
    #ifdef DEBUG
                    printf ("\nRecebi um pedido de listagem (SemID=%d, Shm=%d)", msg.semID, msg.shmID);
    #endif
                    shmptr = shmat(msg.shmID, NULL, 0); /* Attach */
    
    
                    if ((int)shmptr != -1) {   
                
                        if ((fp = fopen("livros.csv", "r")) == NULL) {
                            printf("Nao foi possivel abrir a BD.\n");
                            return EXIT_FAILURE;
                        }
                      
                printf("Numero;Titulo;Tipo;Autor;Editora\n");
                
                        for(int i = 0; fgets(line, 129, fp) != NULL; i++)
                puts(line);
                
                        fclose(fp);
    
    
                        /* Enviar Mensagem com resposta de sucesso ao Cliente */
                        msg.tipo = 13;
    
    
                        if ( msgsnd(filaID, &msg, sizeof(msg), 0) == 0 ) {
                            printf("Pedido executado com sucesso\n");
                        }
                        else {
                            printf("Erro no envio da mensagem\n");
                            return EXIT_FAILURE;
                        }
    
    
    #ifdef DEBUG
                        printf ("Vou desbloquear o semaforo %d\n", msg.semID);
    #endif
                        semop(msg.semID, &UP, 1); /* Desbloquear Cliente no Semaforo */
    
    
                        shmdt(shmptr);     /* Detach */                  
                    }                        
                    break;
      
            }
        } while (msg.tipo != 0);
    
    
        return EXIT_SUCCESS;
    }
    
    
    



    Se alguém me poder dar uma ajudar agradeço, que ando aqui às voltas e não consigo que isto funcione... Se meter os dois semáforos UP ele funciona... mas assim os semáforos não tão lá a fazer nada...

    cumps
     

Partilhar esta Página