|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
[C] Attendere terminazione...
Ciao, dovrei implementare un semplice server che, ricevendo richieste da una pipe nota, crei ad hoc dei processi per soddisfare tali richieste. Ad ogni richiesta, pero', il server (Il processo padre, non i figli !) deve mantenere una media del tempo di esecuzione necessario per soddisfare ciascuna richiesta. Avevo pensato di utilizzare la gettimeofday() prima di mandare in esecuzione il figlio e poi di utilizzare la sigaction() per fare in modo che, alla terminazione del figlio, il segnale SIGCHLD venga gestito mediante una routine apposita che faccia la "seconda" gettimeofday() e quindi permetta al padre di aggiornare tale media. Cosi' facendo, pero', non posso risalire a quale funzione sia stata svolta dal figlio e, pertanto, il server non sa quale delle medie andare ad aggiornare. Spero di essere stato chiaro... o di esserci andato vicino... Sapreste darmi qualche consiglio !?! Escludo l'utilizzo di wait() poiche' renderebbe vano l'utilizzo di processi appositi affinche' il processo padre possa ricevere nuove richieste.
thks
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Invece devi usare proprio la wait o waitpid, altrimenti come fai a sapere quale pid ha generato il segnale?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
Dovrebbe succedere qualcosa del genere: Codice:
... int med1, med2, med3, med4; /*Quattro differenti richieste. Per gni richiesta c'e' una precisa funzione per soddisfarla...*/ /*Il padre riceve una richiesta e la codifica*/ pid = fork(); if (pid==0)/*Processo figlio*/ { /*Esegue la funzione che il padre ha "deciso" debba essere seguita*/ } else {/*Processo padre*/ struct timeval t1, t2; gettimeofday(&t1, NULL); /*Va ad aspettare altre richieste ma e' pronto a fare la seconda gettimeofday() quando il figlio avra' terminato di eseguire la funzione... ma come ?!?*/ .... .... ![]() ![]() ![]() ![]() ![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. Ultima modifica di Ed_Bunker : 07-07-2004 alle 18:05. |
|
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
L'ideale sarebbe avere un modo per trasferire informazione ulteriore dal figlio al padre. Del tipo: quando il figlio termina, oltre ad inviare il SIGCHLD, invia al padre anche il num. che identifica la funzione eseguita ed il tempo che ha impiegato per eseguire tale funzione. Mah...
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Jul 2000
Città: Amsterdam
Messaggi: 217
|
Codice:
The wait4() call provides a more general interface for programs that need to wait for certain child processes, that need resource utilization statistics accumulated by child processes, or that require options. The other wait functions are implemented using wait4(). ![]() UPDATE: Leggo solo adesso...ma non puoi usare socket e far si che ogni richiesta di connessione del figlio faccio forkare un altro processo dal padre che gestisce la connessione mentre il padre originario resta in attesa di altre connessioni? Detto cosi' suona tremendo...provo a scrivertelo copiandolo da alcune dispense: Codice:
while(1) { clientFd = accept(serverFd, clientSockAddrPtr, &clientLen); if ( fork() == 0 ) { VARIEOPERAZ_come_aspettare_che_termini_il_figlio_comunciandoci_anche close (clientFd); exit(0); } else close(clientFd); } Cya! |
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
![]() Seriamente, tieniti una lista di strutture che contengono i vari pid creati, la funzione assegnata al pid e l'istante di inizio processamento. Nel sighandler sfogli la lista fino a trovare quella relativa al tuo pid.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
_ Il processo padre riceve una richiesta dalla pipe _Codifica tale richiesta e si forka per fare in modo che la richiesta venga soddisfatta dal processo figlio _Il processo padre e' adesso disponibile ad accettare nuove richieste _Quando CIASCUN figlio termina il processo il padre se ne deve accorgere perche' e' necessario che mantenga aggiornate le medie dei tempi di esecuzione delle funzioni che i figli utilizzano per soddisfare le richieste
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
gettimeofday. No ?!? Dovrei scorrere ogni volta le struct per controllare quale funzione ha svolto il pid che mi ha mandato la SIGCHLD. Penso ci sia qualcosa si piu' semplice... Potrebbe fare la gettimeofday() il processo figlio e calcolare esso stesso quanto ci vuole per eseguire la funzione "indicata" dal processo padre. E poi, alla terminazione, il processo padre cattura il SIGCHLD e dovrebbe avere il modo di accedere al tempo calcolato dalla gettimeofday del figlio. Che magari gli viene esplicitamente passato dal figlio. Esempio: Codice:
int media1, media2, media3, media4; int main(int argc, char * argv) ... ... /*fd = descrittore in lettura della pipe*/ while (true) { /*Le letture avvengono mediante la codifica a lunghezza variabile dei messaggi: invio la lunghezza del messaggio seguita immediatamente (In una sola write !) dal messaggio stesso*/ int messLength; read(fd, &messLength, sizeof(int)); char * mess = (char*) malloc(sizeof(char) * messLength + 1; read(fd, mess, messLength); mess[messLength] = '\0'; /*Carattere di terminazione*/ char ** fields = split_arg(mess); /*I messaggi sono del tipo: "1 PID" : voglio la lista dei file .txt "2 PID subString" : voglio che sia cercata la stringa subString nei file .txt presenti etc. etc. Il primo campo del messaggio e' quello discriminante per decidere quale funzione debba essere eseguita */ int funType = atoi(field[0]); ... ... if (funType == 2) { int pid; struct sigaction new, old; new.sa_handler = gest; sigaction (SIGCHLD, &new, &old); /*Adesso torno ad aspettare nuove richieste*/ if ((pid = fork()) == 0)/*FIGLIO*/ { struct timeval start, end; getimeofday(&start,NULL); /*Richiama la funzione idonea*/ findString(.../*parametri vari*/...); gettimeofday(&end, NULL); long int time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); exit(2); /*uscendo esplicitamente con codice 2 potrei indicare al padre che ho svolto la funzione 2: e' "sbagliato" fare cosi ?!??*/ } else/*PADRE*/ { /*Torno ad attendere nuove richieste*/ } ... ... } /*Routine per gestire in SIGCHLD*/ void gestisci(int sig) { int status; wait(&status); /*Questa mi dovrebbe restituire lo stato con cui e' uscito il figlio che ha provocato la SIGCHLD. No !?!?*/ ... ... if (status == 2) { /*Adesso dovrei poter accedere alla variabile time per aggiornare la media della funzione corrispondente. Ma come ?!? E quindi fare... */ media2 = @ * media2 + (1 - @) * time; } } ![]() ![]() ![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. Ultima modifica di Ed_Bunker : 08-07-2004 alle 10:02. |
|
![]() |
![]() |
![]() |
#10 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
_Prima_ esegui la gettimeofday, _poi_ cerchi la struct corrispondente al tuo pid.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#11 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
Ovvero: gettimeofday(&end, NULL); /*Dov'e' "end" e' dove trovo "start"*/ Dove la faccio la gettimeofday ? La faccio fare 'completamente' al figlio oppure la 'prima' la fa il processo padre e la 'seconda' la fa la routine di gestione del segnale ? ![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
![]() Il gestore del segnale _è_ il processo padre. E' lui che deve misurare il tempo, non il child (in quanto non dispone di tecniche veloci per passare il valore al padre). Non capisco perché ti preoccupa effettuare la seconda gettimeofday nel sighandler...
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Cmq ho trovato la soluzione più rapida al tuo problema: vedi man sigaction, nella parte che parla di siginfo_t, in particolare la descrizione dei campi si_utime e si_stime
![]()
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
thks
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 02:43.