|
|
|
![]() |
|
Strumenti |
![]() |
#81 |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Quindi tu dici cosi' (schematizzo molto)
con P indico il PADRE "listener" con CH indico il figlio "chat" che si occupa della connessione in ingresso con CN indico "connector" il figlio che tenta di connettersi P: fork // creo CH CH: attendo una connessione per me che viene accettata solo da mio padre P P: fork //creo CN CN: tento di connettermi, se ci riesco passo il socketfd a CH nel caso gli serva P: aspetto connessioni da CN (non dal mio figlio, ma da CN generati da altre istanze del mio software) appena me ne arriva una passo il socketfd al mio CH di competenza. Cosi' funziona in entrambi i casi? caso 1) Mettiamo che il CN riesca a connettersi e deve condividere la connessione con il CH se gli passo il socketfd funzia? caso 2) Il P riceve una connessione e la passa a CH e qui ok, poi magari serve anche al CN gli passa il socketfd funzia? E questo che deve risultare...una sola connessione per 2 processi! |
![]() |
![]() |
![]() |
#82 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Io farei così :
Il processo princiapale può essere "Connector"... Connector fork      Listener      while(1) {      aspetto sulla accept      fork           Chat      } while(1) { Aspetto che venga richiesta una connessione fork      Chat } Ogni processo "Chat" ha il suo socket su cui fa una connessione bidirezionale... |
![]() |
![]() |
![]() |
#83 |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
No aspetta non ho capito: ogni processo Chat che cosa deve fare? Nel senso che io avevo gia' fatto una cosa simile facendo passare i socketfd, ma ilsensine mi ha detto che non funzia, perche' essendo processi differenti non hanno in comune i file descriptor...come devo fare di preciso? Come fanno i 2 processi chat a condividere la medesima connessione (qualora ne venga il bisogno?)
|
![]() |
![]() |
![]() |
#84 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Allora usa i thread
![]() Non una grande esperienza di programmazione multiprocesso in Linux...mi dispiace... |
![]() |
![]() |
![]() |
#85 | |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Quote:
Thanx... |
|
![]() |
![]() |
![]() |
#86 | |
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 |
|
![]() |
![]() |
![]() |
#87 | |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Quote:
ciao Cimmo |
|
![]() |
![]() |
![]() |
#88 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Non è necessario, sono semplici da usare, ti faccio un breve howto:
Include necessario: #include <pthread.h> Quando compili, linka con le libpthread ( -lpthread ) Un thread è un "processo nel processo"; condivide tutta la memoria e i descrittori di file con gli altri thread; ogni thread ha uno stack ("stato") proprio. Creazione di un thread: pthread_t newthread; pthread_create(&new_thread, NULL, funzione, parametro); dove: "funzione" è una funzione di prototipo void *(*) (void *); ad es. void *funzione (void *parametro) Questa funzione sarà l'inizio del nuovo thread. parametro è un void * generico; è un parametro che puoi passare al thread, a tua discrezione. Quando un thread termina deve chiamare pthread_exit(void *retval) dove retval è il parametro di "uscita" del thread, semmai ne hai bisogno. Esempio: Codice:
#include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> void *th_fnc(void *data) { int param = (int) data; for(;;) { fprintf(stderr, "thread %d parametro %d\n", getpid(), param); sleep(1); } } int main() { pthread_t unused; pthread_create(&unused, NULL, th_fnc, (void *) 1); pthread_create(&unused, NULL, th_fnc, (void *) 2); for(;;) { fprintf(stderr, "thread padre\n"); sleep(1); } return 0; } Nota che i thread possono accedere in maniera concorrente a _tutti_ i dati globali, funzioni o altro del processo corrente. Ovviamente ti servono delle strategie di lock, che fanno uso dei pthread_mutex: Inizializzazione di un mutex: pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); Lock di un mutex (equivalente a "EnterCriticalSection" di Windows) pthread_mutex_lock(&mutex) oppure pthread_mutex_trylock(&mutex) per la forma non bloccante (altrimenti il lock è bloccante se il mutex è loccato da qualcun altro). Unlock di un mutex: pthread_mutex_unlock(&mutex); Distruzione di un mutex non più necessario: pthread_mutex_destroy(&mutex); Esempio: Codice:
#include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> int x = 0; int y = 0; pthread_mutex_t mtx; void *th_fnc(void *unused) { for(;;) { pthread_mutex_lock(&mtx); /* Senza il lock, l'incremento di x e y non sarebbe atomico */ x++; y++; fprintf(stderr, "thread %d (x,y)= (%d,%d)\n", getpid(), x, y); pthread_mutex_unlock(&mtx); sleep(1); } } int main() { pthread_t unused; pthread_mutex_init(&mtx, NULL); pthread_create(&unused, NULL, th_fnc, NULL); pthread_create(&unused, NULL, th_fnc, NULL); for(;;) sleep(1); return 0; }
__________________
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 |
![]() |
![]() |
![]() |
#89 |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Ok grazie e 1000, adesso mi metto al lavoro...ma una cosa sulle variabili:
1) se io dichiaro una variabile nel main (padre) poi creo dei thread questa e' condivisa da tutti? Nel senso il primo thread che la cambia, la cambia per tutti? 2) se voglio fare una variabile privata di un thread, mi basta dichiararla all'interno della sua funzione? P.S.= Usando i thread ottimizzo automaticamente per i Pentium 4 HT ![]() P.P.S.= C'e' un baco nel forum...anche se specifichi /CODE ti valuta lo stesso le faccine...sbagliato secondo me...infatti ha riconosciuto il punto e virgola e la parentesi della fine del for... |
![]() |
![]() |
![]() |
#90 | ||||
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Quote:
Quote:
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 |
||||
![]() |
![]() |
![]() |
#91 | |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Quote:
Se invece non lo metto mi dice in fase di compilazione: host.c: In function `thReceive': host.c:434: warning: control reaches end of non-void function host.c: In function `thSend': host.c:538: warning: control reaches end of non-void function strano perche' le 2 funzioni sono void, dalle tue differiscono solo che prendono un puntatore ad un int come input. Che cosa sta succedendo? |
|
![]() |
![]() |
![]() |
#92 | ||
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Quote:
Usando pthread_exit non ottieni quel warning in quanto è una funzione dichiarata con __attribute__ ((__noreturn__)) (in soldoni: non ritorna mai - ma questo è ovvio)
__________________
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 |
||
![]() |
![]() |
![]() |
#93 | |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Quote:
Codice:
for (i=0; i<=(TotHosts-1); i++) { if ((i!=numHost) && (network[0][i].byteReceived>0)) pthread_create(&unused,NULL,thReceive(&i),NULL); if ((i!=numHost) && (i!=0) && (network[0][i].byteSent>0)) pthread_create(&unused,NULL,thSend(&i),NULL); } |
|
![]() |
![]() |
![]() |
#94 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
![]() Che è 'sta roba? ![]()
__________________
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 |
|
![]() |
![]() |
![]() |
#95 | |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Quote:
|
|
![]() |
![]() |
![]() |
#96 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Cerrrto che no
![]() Così stai _chiamando_ la funzione Riguardati bene il mio primo esempio; il parametro si passa così: Codice:
pthread_create(&unused,NULL,thReceive,(void *) i);
__________________
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 |
![]() |
![]() |
![]() |
#97 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Nota inoltre che devi passare il valore di i, non il suo indirizzo, altrimenti ora che il thread legge il valore...il ciclo for l'ha già modificato!
__________________
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 |
![]() |
![]() |
![]() |
#98 | |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Quote:
int i=(int) toHost; e la funzione l'ho dichiarata cosi': void *thSend(void *toHost) va bene? |
|
![]() |
![]() |
![]() |
#99 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Sì, è corretto.
Nota che se devi passare più di un parametro al thread, la procedura comune è allocare dinamicamente una struttura apposita, e passare il puntatore al thread. Sarà compito del thread, quando termina, deallocare la struttura.
__________________
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 |
![]() |
![]() |
![]() |
#100 |
Senior Member
Iscritto dal: Jan 2001
Città: California
Messaggi: 7174
|
Un'altra cosa:
per le risorse in comune: devo gestire la mutua esclusione solo quando la risorsa viene modificata, se una risorsa non viene modificata e viene soltanto letta non ha senso che metta la mutua esclusione giusto? |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 14:10.