Newsgroup: it.comp.os.linux.development
Titolo: Inviare SIGTERM da un processo figlio ad un suo "fratello"

Ciao. Primo post. Per correttezza dico che si tratta di un problema
legato ad un esercizio scolastico e che quindi in caso di snobismo non
potrò prendermela.
Processo padre genera du processi figli: OK in parte 1)
Processi figli 1 e 2 dialogano tramite pipe. OK
Dopo n messaggi comunicati processo figlio 2 deve killare il fratello:
NO 2)
1) Eseguo fork(). Il pid del processo figlio viene salvato in pid1
(int) Es: 5436. Se dal processo 2 o da processo genitore interrogo
pid1 mi torna un numero completamente diverso. Es: -12456789.
2) Stando così le cose non so come ottenere, dal processo figlio 2, il
PID del processo 1 così da killarlo correttamente.
Il codice non lo posto per non appesantire il messaggio ma se qualcuno
si interessa provvedo subito. Grazie in anticipo.
Nicola

 
"interroghi" come?
-- 
SF
"Spartani... mangiate tanto a colazione perchè stasera ceneremo nell'Ade!!"


wrote:

...
dopo n messaggi
// printf("Pid1 =%d\n",pid1); Commentata perché serviva solo a vedere
se pid1 contiene il giusto valore
kill(SIGTERM,pid1);
printf("2nd child process killed 1st child process");
Nicola

 PID del processo 1 così da killarlo correttamente.
faglielo comunicare tramite una pipe pure quello :)


Ok, però nella traccia che abbiamo l'invocazione di
kill(SIGTERM,pid1); funziona.
Siccome vorrei scostarmi dalla traccia ho tirato in piedi un bel
carrozzone (credo) e potrebbe essere questa la causa del mancato
funzionamento.
Ecco il codice:
#include <stdlib.h>
#include <stdio.h>
#include <time.h> // solo per il seme di srand()
#include <unistd.h> // per lavorare sui processi
#include <signal.h> // per l'invio dei segnali
//Tra i processi P1 e P2, figli di P0, devono essere inviati 20
caratteri dopo di che P2 uccide P1
int j;
char letters[26]; // Container for letter
// Inizializza l'array
int fillArray(){
for (j=0;j<27;j++)// Initializes the array with 26 alphabet capital
letters
    letters[j]= (65 + j);
}
// Get a random letter
int getLetter(){
   return letters[(int) rand()%26 ];
}
//Fino a qui non sembrano esserci problemi.
int main(void) {
  //Variables
  int pid; // contains the return value of the fork() call
  int pid1; //contains the 1st child process PID
  int pid2; //contains the 2nd child process PID
  ppid; //contains the parent process PID of both 1st and 2nd child
  int ntimes=1; // counter
  char buffer, tosend;
  int fdes1[2]; // FileDescriptor for 1st child process
  int fdes2[2]; // FileDescriptor for 2nd child process
  //Initializations
  fillArray();
  srand(times(NULL));//
  pipe(fdes1); //creates 1st pipe;
  pipe(fdes2); //creates 2nd pipe;
  ppid = getpid();
  //Creates the 1st child process
  pid = fork();
  if(pid==0){
    printf("I'm the 1st child process, my PID is: %d and my parent's
PID is: %d.-\n",getpid(),getppid());
    pid1 = getpid(); // Qui pid1 contiene il valore corretto.
  //Creates the 2nd child process
  if(pid!=0){
    pid=fork();
    if(pid==0){
      printf("I'm the 2nd child process, my PID is: %d and my parent's
PID is: %d.-\n",getpid(),getppid());
      pid2 =getpid(); // Qui il pid2 contiene il valore
corretto.
    }
  }
Poi c'è il pezzo della trasmissione dei caratteri. Fino a qui cmq
funziona tutto.
Ho pensato anche di salvare i pid in un array di int ma c'è sempre il
fatto che, trattandosi di processi, tutte le variabili vengono
duplicate a seguito della fork e quindi non esistono variabili
condivise...
Per testare il tuo suggerimento: il tipo primitivo dei segnali è un
intero? devo modificare struttura e dimensione del buffer nella pipe?
Nicola

[CUT]
Ecco il pezzo dove avviene la trasmissione:
// Starting to send messages
  if(getpid()==pid1){
         sleep(1);
 		while (read(fdes1[0], &buffer, 1) > 0) {
		     tosend= getLetter();
		     write(fdes2[1], &tosend, 1); // writes on pipe 2
		     printf("1st child receives %s and sends %c\n", &buffer,
tosend);
		     sleep(1);
		}
  }
  if (getpid()==pid2){
    sleep(1);
   	while (read(fdes2[0], &buffer, 1) > 0) {
   	  tosend=getLetter();
   		write(fdes1[1], &tosend, 1); 	// writes on pipe 1
   		printf("2nd child receives %s and sends %c\n", &buffer,
tosend);
   		if(ntimes++==20) // "until P2 has received 20 messages"
   		{
   		  printf("2nd child process(pid %d) kills 1st child process(pid
%d)\n",pid2,pid1);
		  kill(pid1,SIGTERM); //NON VA, qui pid 1 ha il valore astruso di
cui dicevo
   		}
   		sleep(1);
   	}
  }
  if(getpid()==ppid ){//!=pid1 && getpid() != pid2){
    tosend = getLetter();// Character to send
    printf("\nParent sends %c to 1st child\n",tosend);
    sleep(1);
    write(fdes1[1],&tosend,1); \\La prima scrittura devo farla dal
parent perché altrimenti, dato che la read è bloccante, P1 e P2 vanno
in deadlock
    wait();
    sleep(2);
    }
   return 0;
}
Nicola

     pid=fork();
come vedi al padre non hai fatto memorizzare pid1 prima di fare la seconda
fork
quindi devi fare:
if(pid!=0) //ma bastava un else!
{
	pid1=pid;
	pid=fork();
cosi' il processo due eredita anche il pid1 corretto

 cosi' il processo due eredita anche il pid1 corretto
Grazie. Compilato ed eseguito correttamente.
Adesso cerco di capire perché quando stampo a video l'output (1st
child receives... dopo la lettera ricevuta appaiono di volta in volta
caratteri in più: a volte dei punti, a volte segni di paragrafo ecc.
E' una boiata o può dipendere dal tipo di dato?
Nicola
Nicola

 
č una boiata. Praticamente tu riempi "buffer" coi dati ricevuti dalla chiamata 
a read(), ma questo array di char non č null-terminated, percui la stringa 
termina non quando te l'aspetti tu ma al primo carattere '\0' che incontra. 
Per risolvere hai due soluzioni:
1) chiamare
memset( buffer, '\0', sizeof( buffer ));
prima del ciclo di lettura oppure
2) assegnare
buffer[ numero_byte_letti ] = '\0';
-- 
SF
"Spartani... mangiate tanto a colazione perchč stasera ceneremo nell'Ade!!"

 "Spartani... mangiate tanto a colazione perchè stasera ceneremo nell'Ade!!"
Grazie per l'interessamento ma dopo svariate prove non ho capito come
posizionare la 1) o come utilizzare la 2). Per cercare di semplificare
ho eliminato l'array delle lettere ed ora tosend utilizza un intero
che si autoincrementa. La problematica dela fine stringa però permane.
Lo stesso avviene anche dichiarando send e buffer interi anziché char.
Ad ogni esecuzione appaiono i caratteri più disparati.
Mi fa rabbia perché nei tratti principali il mio sorgente non è molto
dissimile dalla traccia però, utilizzando quel sorgente, anche in
diversi cicli di esecuzione non appare il problema dei caratteri
"intrusi".
Nicola

 
eh, il diavolo si nasconde nei dettagli.


 eh, il diavolo si nasconde nei dettagli.
certo, però, riga per riga, il mio sorgente e la traccia sono
praticamente uguali (tipi di dato e ciclo di esecuzione). PERCHE' a me
appaiono i caratteri "fantasma" mentre eseguendo la traccia no???????
UUUUUAAAAAAAAAHHHHHHHHHHHHHH!!!!! scusate lo sfogo.
Nicola
[CUT]

 appaiono i caratteri "fantasma" mentre eseguendo la traccia no???????
perchč evidentemente non sono cosě uguali come credi, e comunque questo te 
l'ho spiegato nel post precedente: se ti compaiono dei caratteri "strani" dopo 
una stringa, significa che a tale stringa manca il carattere '\0' 
(terminatore) nel posto giusto.
-- 
SF
"Spartani... mangiate tanto a colazione perchč stasera ceneremo nell'Ade!!"