Programação C e Bash

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:
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);
 
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);

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.
 
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()".
 
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.
 
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.

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
 
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
 
Só queria avisar que só este ano é que tive disciplinas de informática. Não sou do curso de Engenharia Informática como a maioria das pessoas que aqui participam ou de um curso semelhante que aprendem Linguagem C desde o inicio do curso superior.

Deixo aqui o site da disciplina de SO e como podem ver pelos sumários o professor nunca deu prática de Linguagem C. Só foi dada em Janeiro e o Prof não acrescentou aí na página esses sumários.

T 21.Dez.2007Programação concorrente com semáforos: Produtor-consumidor

Como podem ver foi uma aula Teórica. Queria apenas sugestões como devia fazer o trabalho. Desculpem o incomodo,
Francisco.

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.
 
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:
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

man msgget
man msgrcv
man msgsnd
 
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 (
    report.gif
    ) 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.
 
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.
 
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
 
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.
 
F*dass, não é excelente?! É espectacular! Parabéns!

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*
 
Back
Topo