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

Programação C e Bash

Discussão em 'Programação' iniciada por EngFrancisco, 1 de Fevereiro de 2008. (Respostas: 21; Visualizações: 2547)

  1. Acabei o meu trabalho de SO. Dos mecanismos de comunicação entre processos, que foram sugeridos aqui no fórum:

    - FiFOs;
    - Filas de mensagens e
    - Memória partilhada.

    Utilizei FIFOs. A escolha deste mecanismo de comunicação entre processos deve-se à simplicidade e facilidade de ser implementado, como foi referido na bibliografia que consultei, cujo objectivo era perceber a construção de programas concorrentes que utilizem mecanismos de sincronização como semáforos e sinais.

    Queria agradecer as dicas do: Mr_Miguel, MadOnion, souto, tekker, caskilhas e zyThuM.

    Se quiserem ver o código podem fazer o download em:
    http://francisco.medinformatics.eu/drupal/MIEBIOM_SO.zip

    Agradecia sugestões para melhorar o código. Só consigo compilar em Mac OS X e não consigo fazê-lo em Linux.

    O comando para ligar a impressora é:
    $./impressora.out

    O comando para mandar alguns ficheiros imprimir é:
    $./imprimir.out exemplo1.txt exemplo2.txt & ./imprimir.out exemplo3.txt exemplo4.txt

    Depois para remover o semáforo (porque não consegui integrar no código) é necessário o seguinte comando:
    $./desligar.out

    Cumprimentos,
    Francisco.
     
    Última edição: 9 de Fevereiro de 2008
  2. Mr_Miguel

    Mr_Miguel Power Member

    Aqui vai uma dica:

    Esta string pode ser construída com a função sprintf(). Exemplo:

    Código:
    char comando[512];
    sprintf(comando, "kill -kill %u", numero_que_esta_no_ficheiro);
    
    Depois, é só fazer

    Código:
    system(comando);
    
     
  3. MadOnion

    MadOnion Folding Member

    Podes também ler o numero para uma string.

    Código:
    char str[10];
    
    FILE *fp;
    fp = fopen("nomeficheiro", "r");
    if ( fp == NULL ) {
      perror("Ficheiro sem permissoes");
      exit(1);
    }
    //Assumindo que não é um ficheiro binário, mas sim de texto
    fgets(str, 10, fp);
    close(fp);
    
     
  4. Mr_Miguel

    Mr_Miguel Power Member

    Precisamente. No entanto, (fp == NULL) não significa necessariamente que não temos permissões para aceder ao ficheiro ;) - (fp == NULL) também acontece se o ficheiro não existir.

    Depois de armazenares o número (por exemplo, 40) numa string, que é o que o exemplo do MadOnion faz, tens que o extrair para uma variável que represente um número inteiro. Como os identificadores dos processos são positivos (ou 0), mais vale usarmos um inteiro sem sinal (unsigned int). Extrair um número de uma string é fácil, com a função sscanf:

    Código:
    (...)
    //Assumindo que não é um ficheiro binário, mas sim de texto
    fgets(str, 10, fp);
    close(fp);
    
    unsigned int numero_que_esta_no_ficheiro = 0;
    sscanf(str, "%u", &numero_que_esta_no_ficheiro);
    
    Espero que isto te ajude no que diz respeito a leitura de ficheiros em C.
     
  5. Mr_Miguel

    Mr_Miguel Power Member

    Isso é o código todo? É que se for, nem é suposto isso compilar. Estás a fazer "sprintf()" para uma variável denominada "imprime", que nem sequer está declarada!

    Mais ainda, se queres matar o processo filho, porquê o uso do comando "kill" na bash? Se é suposto o pai esperar que o filho morra, fará mais sentido utilizar a função "wait()" ou "waitpid()".
     
  6. souto

    souto To fold or to FOLD?

    Uma generalização desse problema é o conhecido padrão do produtor-consumidor, ou em inglês, producer-consumer problem.

    Se googlares um pouco, vais entender porquê.

    Começa por aprender o que um fork() faz, depois investiga o problema de partilhar variáveis entre threads do mesmo processo sem mecanismos de sincronização. Depois vê o que são semáforos... e depois volta a ler o problema do produtor-consumidor e tenta ver uma implementação deste em C.

    Qualquer temática que referi em cima pode ser encontrada num livro de introdução a sistemas operativos.

    Boa sorte e cumprimentos.
     
  7. MadOnion

    MadOnion Folding Member

    Citando o souto, o que ele quis dizer, foi:
    Se tiveres vários processos filhos, com um unico pai, vais ter que usar mecanismos de sincronização(os tais semáforos), para que os filhos não mandem imprimir tudo ao mesmo tempo.
    Se um processo filho mandar imprimir, mais ninguém(digo outros processos filhos) devem imprimir(chamamos a isto secção critica, ou critical section), os seus ficheiros que estão na fila de espera para impressão(ver spooler e spooling).

    Cumps
     
  8. Mr_Miguel

    Mr_Miguel Power Member

    Compreendo que, para alguém que só tem 2 semanas de C, "comunicação entre processos" seja um tópico bastante difícil. Por essa razão, acho estranho que te tenha sido pedido um trabalho relativo a esse tópico. Eu tive uma cadeira denominada "Sistemas Operativos" onde aprendi isso tudo gradualmente.

    Colocando as estranhezas de lado, tu não precisas de implementar a função "wait()" nem a função "waitpid()". Elas estão na biblioteca sys/wait.h. A função "wait()" serve para esperar que um dos processos filhos, criados pelo "fork()", termine - e quando digo "um", digo que pode ser qualquer um deles; deste modo, se tiveres N processos filhos e quiseres esperar por eles todos, o processo pai tem que fazer N chamadas à função "wait()".

    A função "waitpid()" serve para esperar por um processo filho em particular. É mais poderosa que a função "wait()", na medida em que podes fazer com que, em vez de esperar por alguém, verifique se um processo filho já terminou ou não. Dado o que apresentaste nesta thread sobre o funcionamento do trabalho, eu diria que a função "wait()" é suficiente.

    Em termos de código, a função "wait()" chama-se tipicamente do seguinte modo:
    Código:
    wait(NULL);
    Para uma especificação completa destas funções, ver http://linux.die.net/man/2/wait
     
  9. Tekker

    Tekker Power Member

    Ok, tendo a teoria não é tao dificil.
    Vais precisar de uma zona de memória partilhada e de semáforos.
    Para semáforos, aconselho que uses a norma POSIX. Para a memória partilhada, parece-me que SystemV é mais fácil.
    Basta googlares por 'semaphores posix', e 'shared memory systemv' e encontras uma série de exemplos.
    Também encontras muitas versões do produtor-consumidor em C, basta procurares um pouco ;)

    qualquer duvida mais concreta xuta.

    boa sorte.
     
  10. Boas Francisco!!

    Para esse problema eu pensei de forma diferente. Utilizas uma Message Queue onde colocas todos os pedidos (endereços dos ficheiros a imprimir) e depois crias uma aplicação que vai buscar á fila cada arquivo que queres imprimir.
    Penso que assim podes solucionar os problemas de concorrência.

    Gosto deste tipo de comunidades activas aonde os membros se ajudam mutuamente e espero que assim continue.

    Abraço
     
    Última edição: 4 de Fevereiro de 2008
  11. zyThuM

    zyThuM Power Member

    man msgget
    man msgrcv
    man msgsnd
     
  12. HecKel

    HecKel The WORM

    Thread mais do que limpa!
    Vamos lá a ver umas coisas:
    1. Se há mensagens provocativas ou offtopic, façam report! É para isso que este icon ([​IMG]) maravilha serve, não alimentem discussões paralelas, sff!
    2. Se não querem/sabem ajudar, não se metam a mandar bocas. Cada um sabe da sua vida, cada um sabe como gere o seu tempo. Se para uns é desperdício de tempo tentar perceber alguns conceitos mais básicos na época de exames, para outros é visto como algo a tentar. O autor da thread não pediu ninguém para lhe fazerem um trabalho, essas são as únicas threads em que de facto tem algum sentido comentar tal pedido.
    Sobre esta limpeza, considerem como um bónus. Alimentar offtopics também pode dar origem a avisos, os reports servem para isto mesmo.

    Continuem a discussão, mas com isto em conta, sff.
     
  13. Mr_Miguel

    Mr_Miguel Power Member

    Antes de mais, parabéns pela conclusão do trabalho. Segundo, não vejo porque é que o código não compilaria em Linux. Peço-te então que postes os erros de compilação.

    Cumprimentos.
     
  14. Erros ao compilar em Linux

    Obrigado Mr_Miguel. O erro que dá ao compilar em Linux é o seguinte:

    $ gcc impressora.c
    impressora.c: In function ‘main’:
    impressora.c:19: error: storage size of ‘arg’ isn’t known


    Porquê que em Mac OS X não dá problema na compilação e em Linux dá este erro. O meu SO é MAC OS X por isso não tenho problema. Mas compilar nos pc´s dos meus colegas em Linux não consigo.
     
  15. Ace-_Ventura

    Ace-_Ventura Power Member

    Pelo que eu vi pode ser falta da estrutura por algum motivo no gcc. faz isto
    Código:
       #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
       /* union semun is defined by including <sys/sem.h> */
       #else
       /* according to X/OPEN we have to define it ourselves */
       union semun {
             int val;                    /* value for SETVAL */
             struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
             unsigned short int *array;  /* array for GETALL, SETALL */
             struct seminfo *__buf;      /* buffer for IPC_INFO */
       };
       #endif
    Google power :-D
     
  16. Obrigado Ace-_Ventura. Sim agora a compilação, em Linux, não dá erros. No entanto, não funciona correctamente.

    Hoje entreguei o trabalho e no relatório estava a informação que foi compilado em Mac OS X. Como o professor utiliza também Mac OS X não deve existir problema. Mas já agora gostaria de saber porque não funciona correctamente em Linux.
     
  17. Nota do Trabalho

    Agradeço a todos os que colaboraram. Já saiu a nota do trabalho...tive 16 valores. ;)

    Obrigado,
    Francisco.
     
  18. MadOnion

    MadOnion Folding Member

    Não é uma nota excelente, mas é uma boa nota.
    Afinal de contas, valeu a pena o esforço, ou não? :P
     
  19. Baderous

    Baderous Banido

    F*dass, não é excelente?! É espectacular! Parabéns!
     
  20. Mr_Miguel

    Mr_Miguel Power Member

    Tenho que concordar. Consideremos que estamos perante alguém que não trabalha propriamente na área da informática... Tirar uma nota dessas numa cadeira de Sistemas Operativos é... Indescritivelmente bom! Também dou os meus parabéns, com certeza!

    Só é pena eu também não saber essa coisa dos semáforos. Gosto mais de trabalhar com semáforos POSIX (também conhecidos por "named semaphores").

    Mais uma vez, parabéns. Atrevo-me a dizer que és dos poucos que conheço que se esforçam mesmo por saber programar. *aplauso*
     

Partilhar esta Página