Sto facendo (per esigenze didattiche) un programma (in C) che crea due figli, ognuno dei due deve contare per lo stesso file quante righe hanno più di N caratteri. Ogni figlio si occupa di un carattere diverso. Ogni volta che un figlio trova una riga con più di N caratteri lo segnala al padre con SIGUSR1/SIGUSR2.
Il problema è che la funzione che conta, conta correttamente, ma il padre sembra ricevare al massimo 1 SIGUSR1/SIGUSR2. Cioè se un figlio non trova linee, non manda segnali, tutto ok. Se ne trova una, manda un SIGUSR1/2, tutto ok. Ma se ne trova più di una allora il padre sembra comunque rilevare un solo SIGUSR1/2.
Mi chiedo se, quando un processo manda un segnale più volte ad un altro processo, il processo destinatario entra nella routine di servizio per tutte le volte che riceve il segnale, o una volta per tutte.
Io posto il codice, ma è abbastanza lungo e non so quanto abbiate voglia di mettervi a leggerlo, quindi se potete chiaritemi solo la questione dei segnali.
Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
void print_usage(){
printf("Usage: contaCaratteri <c1> <c2> <N> <fileIn> <fileOut>\n");
}
int N, lines1, lines2, terminated;
void conta(int fd, char c, int signum);
void lines(int signum);
void handler(int signum);
void wait_child();
int main(int argc, char ** argv){
int fdOut, fdIn, i;
int pid;
char c1, c2;
char msg1[50], msg2[50];
lines1 = 0;
lines2 = 0;
terminated = 0;
if(argc != 6){
print_usage();
exit(-1);
}
N = atoi(argv[3]);
c1 = argv[1][0];
c2 = argv[2][0];
if((fdIn = open(argv[4], O_RDONLY)) == -1){
printf("Il file in lettura non esiste.\n");
exit(-1);
}
close(fdIn);
if((signal(SIGUSR1, lines)) == SIG_ERR)
perror("Prima signal non riuscita\n");
if((signal(SIGUSR2, lines)) == SIG_ERR)
perror("Seconda signal non riuscita\n");
if((signal(SIGTERM, handler)) == SIG_ERR)
perror("Terza signal non riuscita\n");
for(i = 0; i < 2; ++i){
pid = fork();
if(pid == 0){
if(i == 0){
if((fdIn = open(argv[4], O_RDONLY)) == -1){
printf("Errore nell'apertura del file in lettura.\n");
exit(-1);
}
conta(fdIn, c1, SIGUSR1);
kill(getppid(), SIGTERM);
exit(0);
}
else if (i == 1){
if((fdIn = open(argv[4], O_RDONLY)) == -1){
printf("Errore nell'apertura del file in lettura.\n");
exit(-1);
}
conta(fdIn, c2, SIGUSR2);
kill(getppid(), SIGTERM);
exit(0);
}
}
else if (pid < 0)
perror("Fork error");
}
while(terminated != 2);
/* Scrittura risultato in fileOut */
if((fdOut = open(argv[5], O_WRONLY|O_CREAT, 0755)) == -1){
printf("Errore nell'apertura del file in scrittura.\n");
exit(-1);
}
sprintf(msg1, "Il file contiene %d linee con più di %d occorrenze di %c\n", lines1, N, c1);
sprintf(msg2, "Il file contiene %d linee con più di %d occorrenze di %c\n", lines2, N, c2);
if((write(fdOut, msg1, strlen(msg1))) < strlen(msg1))
printf("Errore in scrittura del file.\n");
if((write(fdOut, msg2, strlen(msg2))) < strlen(msg2))
printf("Errore in scrittura del file.\n");
close(fdOut);
wait_child();
}
/* Raccolta stato figli */
void wait_child(){
int i, status, pid;
for(i = 0; i < 2; i++){
pid = wait(&status);
if(WIFEXITED(status)){
printf("Il processo figlio con pid %d è terminato volontariamente con stato %d\n", pid, WEXITSTATUS(status));
}
else if (WIFSIGNALED(status))
printf("Il processo figlio con pid %d è terminato involontariamente a causa del segnale %d\n", pid, WTERMSIG(status));
}
}
void conta(int fd, char c, int signum){
char buff[1];
int occurrance = 0;
while(read(fd, buff, 1) > 0){
if(buff[0] == '\n'){
if(occurrance > N){
kill(getppid(), signum);
}
occurrance = 0;
}
else if (buff[0] == c)
++occurrance;
}
close(fd);
return;
}
void lines(int signum){
if(signum == SIGUSR1)
lines1++;
else if(signum == SIGUSR2)
lines2++;
return;
}
void handler(int signum){
terminated++;
return;
}