[C] Padre pari e dispari

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
crismon_01
Prode Principiante
Messaggi: 110
Iscrizione: mercoledì 4 ottobre 2017, 21:34
Desktop: K
Distribuzione: Ubuntu
Sesso: Maschile

[C] Padre pari e dispari

Messaggio da crismon_01 »

Saalve, sto facendo un programma che dato un processo padre creato l' eseguibile quando lo eseguo e gli do tot parametri se il processo padre è pari attiva i suoi figli dispari e questi uno a uno eseguono i comandi da terminale dati come parametro, se il padre ha un pid disparo attiva i figli pari che eseguono i comandi passati come parametro con l' eseguibile: ho fatto così:

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

typedef char str [20];

void handler(int signal){
	if(signal==SIGUSR1){		//p pari
			if(getpid()%2){
				exit(1);
			}
		}
	else{				//p disp
		if(getpid()%2==1)
			exit(1);

	}
}

int main(int argc, char *argv[]){
pid_t pid[argc];
int status,i;
for(i = 1;i<=argc;i++){
	pid[i] = fork();
	if(pid[i]<0)
		exit(9);
	else if(pid[i]>0){
		printf("PID PADRE: %d\n",getpid());
		if(pid[i]%2==0){		//p pari
			kill(0,SIGUSR1);
			}
		else{				//p dispari
			kill(0,SIGUSR2);
			}
		}
		else{
			printf("PID FIGLIO: %d\n",getpid());
			signal(SIGUSR1,handler);
			signal(SIGUSR2,handler);
			pause();
			str s = "./cia";
			strcat(s,argv[i]);
			execlp(s,s,NULL);
			exit(1);
		}

}//for

}//main
ma da terminale esce sempre così:
stampa pid del padre (giusto)
segnale 1(o2) definito dall' utente e termina l' esecuzione (sbagliato)
qualcuno me lo chiarirebbe e mi potrebbe spiegare come potrebbe fare un padre con pid dispari a attivare solo dei figli quelli con pid pari e viceversa?
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: [C] Padre pari e dispari

Messaggio da melfnt »

Ciao!
L'approccio che stai usando va bene: siccome non hai il controllo sul pid dei processi dei figli, l'unica soluzione che ti resta è quella di attivare dei processi figli poi decidere se ucciderli o lasciarli continuare a seconda della parità del loro pid. Spero sia solo un esercizio, perché fatico a trovare un'utilità ad un programma del genere :)

Venendo al codice, penso che questa riga sia sbagliata:

Codice: Seleziona tutto

kill(0,SIGUSR1);
Infatti, dal manuale di kill:

Codice: Seleziona tutto

int kill(pid_t pid, int sig);

       If pid is positive, then signal sig is sent to the process with the  ID
       specified by pid.

       If pid equals 0, then sig is sent to every process in the process group
       of the calling process.

       If pid equals -1, then sig is sent to every process for which the call‐
       ing  process  has  permission  to  send  signals,  except for process 1
       (init), but see below.

       If pid is less than -1, then sig  is  sent  to  every  process  in  the
       process group whose ID is -pid.

Tu dovresti mandare il segnale solo ad un figlio, specificandone il pid, e non a tutti i figli, specificando 0.

Inoltre, ti consiglio di ristrutturare il funzionamento dei figli in questo modo: se ricevono SIGUSR1 muoiono, se ricevono SIGUSR2 continuano l'esecuzione (indipendentemente dal loro pid).
Nel padre, decidi se inviare SIGUSR1 oppure SIGUSR2 a seconda delle parità: se la parità è la stessa invii SIGUSR1 (e il figlio muore), altrimenti invii SIGUSR2 (e il figlio continua). Così semplifichi un po' il codice, inoltre al posto di SIGUSR1 puoi inviare direttamente SIGINT o SIGTERM.

Un'ultima cosa, non so se nell'esercizio era prevista: supponiamo che tu passi al padre 5 comandi come parametri, che il padre abbia pid pari e che due figli abbiano pid pari e gli altri tre dispari.
In questo caso, vengono eseguiti solo 3 comandi, dai figli che hanno pid dispari, come si deve comportare il programma? Va bene eseguire solo 3 comandi su 5 oppure devi riprovare ad eseguire gli altri, finché non li hai eseguiti tutti?

;)
crismon_01
Prode Principiante
Messaggi: 110
Iscrizione: mercoledì 4 ottobre 2017, 21:34
Desktop: K
Distribuzione: Ubuntu
Sesso: Maschile

Re: [C] Padre pari e dispari

Messaggio da crismon_01 »

melfnt [url=https://forum.ubuntu-it.org/viewtopic.php?p=5043333#p5043333][img]https://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Ciao!
L'approccio che stai usando va bene: siccome non hai il controllo sul pid dei processi dei figli, l'unica soluzione che ti resta è quella di attivare dei processi figli poi decidere se ucciderli o lasciarli continuare a seconda della parità del loro pid. Spero sia solo un esercizio, perché fatico a trovare un'utilità ad un programma del genere :)

Venendo al codice, penso che questa riga sia sbagliata:

Codice: Seleziona tutto

kill(0,SIGUSR1);
Infatti, dal manuale di kill:

Codice: Seleziona tutto

int kill(pid_t pid, int sig);

       If pid is positive, then signal sig is sent to the process with the  ID
       specified by pid.

       If pid equals 0, then sig is sent to every process in the process group
       of the calling process.

       If pid equals -1, then sig is sent to every process for which the call‐
       ing  process  has  permission  to  send  signals,  except for process 1
       (init), but see below.

       If pid is less than -1, then sig  is  sent  to  every  process  in  the
       process group whose ID is -pid.

Tu dovresti mandare il segnale solo ad un figlio, specificandone il pid, e non a tutti i figli, specificando 0.

Inoltre, ti consiglio di ristrutturare il funzionamento dei figli in questo modo: se ricevono SIGUSR1 muoiono, se ricevono SIGUSR2 continuano l'esecuzione (indipendentemente dal loro pid).
Nel padre, decidi se inviare SIGUSR1 oppure SIGUSR2 a seconda delle parità: se la parità è la stessa invii SIGUSR1 (e il figlio muore), altrimenti invii SIGUSR2 (e il figlio continua). Così semplifichi un po' il codice, inoltre al posto di SIGUSR1 puoi inviare direttamente SIGINT o SIGTERM.

Un'ultima cosa, non so se nell'esercizio era prevista: supponiamo che tu passi al padre 5 comandi come parametri, che il padre abbia pid pari e che due figli abbiano pid pari e gli altri tre dispari.
In questo caso, vengono eseguiti solo 3 comandi, dai figli che hanno pid dispari, come si deve comportare il programma? Va bene eseguire solo 3 comandi su 5 oppure devi riprovare ad eseguire gli altri, finché non li hai eseguiti tutti?

;)
L' esercizio non prevede di eseguire per forza tutti i comandi, comunque non so come fare il metodo di handler, ovvero quello che ti specifica l' azione dopo aver preso il segnale, tu come lo faresti?
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: [C] Padre pari e dispari

Messaggio da melfnt »

crismon_01 [url=https://forum.ubuntu-it.org/viewtopic.php?p=5043354#p5043354][img]https://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto: L' esercizio non prevede di eseguire per forza tutti i comandi, comunque non so come fare il metodo di handler, ovvero quello che ti specifica l' azione dopo aver preso il segnale, tu come lo faresti?
Io lo farei così (pseudocodice):

Codice: Seleziona tutto

se il segnale è SIGUSR1:
    esci
se il segnale è SIGUSR2:
    continua l'esecuzione
e nel padre, dopo la fork :

Codice: Seleziona tutto

se il pid del padre ha la stessa parità del pid del figlio:
    manda SIGUSR1 al figlio
altrimenti:
    manda SIGUSR2 al figlio
L'importante è, come ti dicevo prima, che mandi i segnali solo al figlio appena creato, non a tutti!
Non ti scrivo il codice C perché è un esercizio e dovresti riuscire a farlo da solo :)
crismon_01
Prode Principiante
Messaggi: 110
Iscrizione: mercoledì 4 ottobre 2017, 21:34
Desktop: K
Distribuzione: Ubuntu
Sesso: Maschile

Re: [C] Padre pari e dispari

Messaggio da crismon_01 »

melfnt [url=https://forum.ubuntu-it.org/viewtopic.php?p=5043418#p5043418][img]https://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:
crismon_01 [url=https://forum.ubuntu-it.org/viewtopic.php?p=5043354#p5043354][img]https://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto: L' esercizio non prevede di eseguire per forza tutti i comandi, comunque non so come fare il metodo di handler, ovvero quello che ti specifica l' azione dopo aver preso il segnale, tu come lo faresti?
Io lo farei così (pseudocodice):

Codice: Seleziona tutto

se il segnale è SIGUSR1:
    esci
se il segnale è SIGUSR2:
    continua l'esecuzione
e nel padre, dopo la fork :

Codice: Seleziona tutto

se il pid del padre ha la stessa parità del pid del figlio:
    manda SIGUSR1 al figlio
altrimenti:
    manda SIGUSR2 al figlio
L'importante è, come ti dicevo prima, che mandi i segnali solo al figlio appena creato, non a tutti!
Non ti scrivo il codice C perché è un esercizio e dovresti riuscire a farlo da solo :)

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

typedef char str[10];
str s;
void handler(int signal){
	if(signal==SIGUSR1){	//p pari
		if((getpid()/2)==1){	//f disp
			printf("SONO ATTIVO\n");
			execlp(s,s,NULL);	
		}
		else{	printf("PROCESSO NON ATTIVO\n");
			kill(getpid(),SIGINT);
			}
		}
	else{			//p disp
		if((getpid()/2)==0){	//f disp
			printf("SONO ATTIVO\n");
			execlp(s,s,NULL);
			}
		else{	printf("NON SONO ATTIVO\n");
			kill(getpid(),SIGINT);
			}		
	}
}

int main(int argc,char *argv[]){
pid_t pid;
int status,i;
for(i=1;i<argc;i++){
	strcpy(s,argv[i]);
	signal(SIGUSR1,handler);
	signal(SIGUSR2,handler);
	pid=fork();
	if(pid<0)  exit(9);
	else if(pid==0){
		pause();
		execlp(s,s,NULL);
		exit(1);
	}
	else{
		if((getpid()/2)==0)
			kill(pid,SIGUSR1);
		else 	kill(pid,SIGUSR2);
		sleep(3);
		wait(&status);
	}

}//for 

}//main
provato a fare coì ma in output va sempre sul 4° braccio dell' handler
non so perchè
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: [C] Padre pari e dispari

Messaggio da melfnt »

crismon_01 [url=https://forum.ubuntu-it.org/viewtopic.php?p=5043451#p5043451][img]https://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

typedef char str[10];
str s;
void handler(int signal){
	if(signal==SIGUSR1){	//p pari
		if((getpid()/2)==1){	//f disp
			printf("SONO ATTIVO\n");
			execlp(s,s,NULL);	
		}
		else{	printf("PROCESSO NON ATTIVO\n");
			kill(getpid(),SIGINT);
			}
		}
	else{			//p disp
		if((getpid()/2)==0){	//f disp
			printf("SONO ATTIVO\n");
			execlp(s,s,NULL);
			}
		else{	printf("NON SONO ATTIVO\n");
			kill(getpid(),SIGINT);
			}		
	}
}

int main(int argc,char *argv[]){
pid_t pid;
int status,i;
for(i=1;i<argc;i++){
	strcpy(s,argv[i]);
	signal(SIGUSR1,handler);
	signal(SIGUSR2,handler);
	pid=fork();
	if(pid<0)  exit(9);
	else if(pid==0){
		pause();
		execlp(s,s,NULL);
		exit(1);
	}
	else{
		if((getpid()/2)==0)
			kill(pid,SIGUSR1);
		else 	kill(pid,SIGUSR2);
		sleep(3);
		wait(&status);
	}

}//for 

}//main
provato a fare coì ma in output va sempre sul 4° braccio dell' handler
non so perchè
Non ho capito, quello sarebbe l'implementazione del mio pseudocodice? Secondo me il problema si può risolvere molto più facilmente di così: l'unica cosa che deve fare il figlio è terminare l'esecuzione se riceve SIGUSR1 e andare avanti se riceve SIGUSR2. Sarà invece il padre ad occuparsi di quale segnale mandare ad ogni figlio per farlo continuare o terminare, visto che conosce sia il proprio pid che quello dei figli.

Siccome è la terza volta che lo ripeto, c'è qualcosa che non ti è chiaro in quanto ti sto suggerendo? Pensi che questo metodo non funziona? O hai difficoltà ad implementarlo?

:)
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 9 ospiti