Newsgroup: it.comp.lang.c
Titolo: Problema:signal sotto unix

Ho un problema con la chiamata di sistema signal sotto unix.
In un programma semplicissimo di 20-30 righe, il tipico programma vediamo
come funziona, devo creare 5 processi slave e poi ogni 5 secondi devo
ucciderne uno. La funzione signal dove va messa? E la kill per uccidere i
processi?
Cosa serve effettivamente la signal?
Vi ringrazio anticipatamente per l'aiuto, se potete rispondete sia al mio
indirizzo e-mail che nel newsgroup. Grazie.
-- 
Posted from 
relay4.inwind.it
 [212.141.53.75] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

ti mando una possibile soluzione...
per rispondere alla tua domanda sulla signal: si tratta di una funzione che
dichiara quale gestore (secondo parametro) dev'essere invocato quando al
processo che la invoca viene recapitato un determinato segnale (primo
parametro).
nel codice di seguito, ogni figlio dichiara che vuole gestito il segnale di
SIGUSR1 da una invocazione a myHandler.
consiglio comunque alcune pagine del manuale...
    man 2 kill
    man 2 signal
    man 2 wait
    man 2 pause
    man 2 fork
buon divertimento,
    rony.
p.s. il codice compila con gcc sotto Linux, anche se al momento non posso
dare dati più precisi (quella macchina è stato spenta!).
--
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
"Solo due cose sono infinite,
l'universo e la stupidita' umana,
e non sono sicuro della prima."
Albert Einstein
------------------------------------- main.c
// inclusione per kill e signal
#include <sys/types.h>
#include <signal.h>
// serve per la chiamata di getpid...
#include <unistd.h>
// inclusione per output su terminale
#include <stdio.h>
#define PROCESS_COUNT 5
#define TIME_TO_WAIT  1
void myHandler(int s) {
  fprintf(stderr, "%d:\tricevuto un segnale(%d)\n", getpid(), s);
  return;
}
int main(int argn, char* argv[]) {
  int i;
  pid_t pids[PROCESS_COUNT];
  for (i=0; i<PROCESS_COUNT; i++)
    if ((pids[i] = fork()) == 0) {
      // ogni processo figlio dichiara che rispondera'
      // con "myHandler" al segnale SIGUSR1
      signal(SIGUSR1, myHandler);
      // i figli aspettano un qualsiasi segnale
      pause();
      // a questo punto il segnale e' stato gestito...
      // e non resta che questo laconico output!
      fprintf(stderr, "%d:\tmuoio\n", getpid());
      // uscita... il ciclo non dev'essere eseguito
      // anche dai figli!!!
      exit(0);
    }
  fprintf(stderr, "%d:\tfigli creati!\n", getpid());
  // ora i processi figli sono stati creati...
  // e vanno uccisi (il C li fa e poi li accoppa)
  for (i=0; i<PROCESS_COUNT; i++) {
    sleep(TIME_TO_WAIT);
    fprintf(stderr, "%d:\t\"Killo\" %d\n", getpid(), pids[i]);
    kill(pids[i], SIGUSR1);
  }
  // attendo che tutti abbiano terminato...
  // (si ignori il parametro...)
  wait(pids);
  fprintf(stderr, "%d:\tmuoio anch'io\n", getpid());
  return 0;
}

ho riletto il codice e il messaggio... e ho notato che ho dimenticato di
dire una cosa per niente banale: la funzione di libreria kill, com'anche il
programma batch kill, non UCCIDONO un processo, ma gli recapitano un
segnale. per quanto riguarda la versione per riga di comando, il segnale di
default che viene recapitato è quello di terminazione (controllata,
possibilmente).
notate quindi che i figli muoiono perché questa è la semantica che ho voluto
dare io al programma... ma lo fanno perché invocano exit(int), non perché
hanno ricevuto un segnale.
forse questo programma è più carino...
(lo si prenda per demo di signal/kill, e non della sincronizzazione tra
processi: da quel punto di vista ha un enorme problema... ;P )
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define SHOT_COUNT        5
#define SHIELD_PROTECTION 80
// questa variabile mantiene il PID dell'avversario.
pid_t opponent;
// questo e' l'handler del SIGUSR1:
// a seconda della protezione estratta, para o meno
// il colpo. se il colpo non viene parato, prima di
// morire, comunica all'avversario di essere morto!
void Shield(int signal) {
  int sh;
  sh = (int)(random() % 100);
  if (sh <= SHIELD_PROTECTION)
    printf("%d:\tColpo parato! (%d)\n", getpid(), sh);
  else {
    printf("%d:\tARGH! Muoio!  (%d)\n", getpid(), sh);
    kill(opponent, SIGUSR2);
    exit(1);
  }
}
// l'handler del SIGUSR2, semplicemente termina
// il processo, avendo vinto!
void Success(int signal) {
  printf("%d:\tHO VINTO!!!!\n", getpid());
  exit(0);
}
int main(int argn, char* argv[]) {
  // registrazione dei gestori...
  signal(SIGUSR1, Shield);
  signal(SIGUSR2, Success);
  // questo assegnamento ha senso solo per il padre...
  opponent = fork();
  // inizializzo in modo diverso il valore del random
  srandom(getpid());
  // ... il figlio aggiusta cosi' il tiro...
  if (opponent == 0)
    opponent = getppid();
  else
    pause();
  // N.B. faccio iniziare il figlio, per
  // esser sicuro che "opponent" sia valido...
  for(;;) {
    kill(opponent, SIGUSR1);
    pause();
