|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Feb 2005
Città: Cosenza
Messaggi: 425
|
Linux system calls - fork()
Ho un piccolo problema (in realtà è un dramma) con il mio codice.
E' molto semplice: ho due processi, entrambi devono lavorare sullo stesso oggetto ma i cambiamenti fatti da uno di questi sono invisibili all'altro. Non riporto tutto il codice perchè è molto lungo e comunque il problema è abbastanza semplice da poter essere astratto. Ecco qua: Codice:
int pid1, pid2; MyObject *myObject = new Object(); // quest'oggetto ha un campo "nome" void processoUno(void); void processoDue(void); int main(int argc, char *argv[]) { int tpid, status; strcpy(myObject->nome, "Mario"); pid1 = fork(); if(pid1 == 0) { processoUno(); } pid2 = fork(); if(pid2 == 0) { processoDue(); } tpid = wait(&status); tpid = wait(&status); return 0; } void processoUno() { strcpy(myObject, "Luca"); for(;;) { // fa qualcosa } } void processoDue() { cout << myObject->nome << endl; // ERRORE - mi aspetto di leggere Luca, invece leggo Mario...why? T_T for(;;) { // fa qualcosa } } Mi sa proprio che il problema sta nella mia scarsa conoscenza del funzionamento delle system call. I processi creati con fork hanno una copia del codice e dei dati del padre, ma pensavo che essendo myObject una variabile globale il problema non sussistesse... Grazie per qualsiasi aiuto
__________________
![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Aug 2001
Città: San Francisco, CA, USA
Messaggi: 13826
|
fork() copia completamente un processo, e se non sbaglio copia anche la "heap" e lo "stack".
Quindi si crea un processo figlio che è l'esatta copia (o quasi) del padre con il suo spazio di memoria. L'unico modo di trasmettere al figlio è di usare IPC , Sockets o pipes. Potresti usare "clone" per quello che vuoi fare tu che crea un processo che condivide parte dello spazio di memoria del padre con il figlio, però io non l'ho mai usata questa funzione, perciò posso dirti poco ![]() Ciao
__________________
GPU Compiler Engineer |
![]() |
![]() |
![]() |
#3 |
Member
Iscritto dal: Sep 2005
Messaggi: 114
|
la riga di codice cosi' definita
pid_t fork(void); - crea un nuovo processo con indice pid - lo spazio di indirizzamento del nuovo processo è un duplicato di quello del padre - padre e figlio hanno due tabelle dei descrittori di file diverse (il figlio ha una copia di quella del padre) - MA …. condividono la tabella dei file aperti (e quindi anche il puntatore alla locazione corrente di ogni file) - restituisce 0 al figlio e pid al padre, oppure -1 (solo al padre) in caso di fallimento |
![]() |
![]() |
![]() |
#4 |
Member
Iscritto dal: Apr 2004
Messaggi: 130
|
Il comportamento che osservi e' assolutamente corretto. E' cosi' che funziona la fork().
Forse potresti essere interessato ad usare i thread. Codice:
#include <stdio.h> #include <string.h> #include <pthread.h> #include <semaphore.h> char nomeGlobale[256]; sem_t flag; void *threadUno(void* unused); void *threadDue(void* unused); int main(int argc, char *argv[]) { pthread_t tid1, tid2; strcpy(nomeGlobale, "Mario"); sem_init(&flag, 0, 0); pthread_create(&tid1, NULL, &threadUno, NULL); pthread_create(&tid2, NULL, &threadDue, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0; } void *threadUno(void *unused) { strcpy(nomeGlobale, "Luca"); sem_post(&flag); return NULL; } void *threadDue(void *unused) { sem_wait(&flag); puts(nomeGlobale); return NULL; } Nell'esempio ho utilizzato un semaforo (sem_*) per assicurarmi che il secondo thread acceda alla variabile globale solo dopo il primo thread. |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Dec 2002
Città: Bologna
Messaggi: 483
|
come già detto dagli altri prima di me, il comportamento che tu noti non è sbagliato...Linux usa a default un modello a processi pesanti con memoria non condivisa...al momento della fork() viene duplicato l'intero spazio di indirizzamento del processo, compreso le sezioni dei dati, dello stack e dell'heap...l'unica cosa che i due processi condividono è la sezione di codice visto che Linux usa un modello a codice puro (la condivisione è attuata lato kernel...non è visibile) e i fd aperti (questo vuol dire che se il padre apre un file, il figlio eredita il file aperto e se effettua una lettura sposta la testina in avanti anche per il padre...).
Per avere gli effetti che desideri tu devi usare la libreria pthread, consideranto però che in questo caso devi gestire correttamente gli accessi concorrenti alle variabili condivise mediante l'uso di semafori....
__________________
Acer TravelMate 8103Wlmi |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Feb 2005
Città: Cosenza
Messaggi: 425
|
Grazie a tutti per le risposte.
Utilizzare i thread sarebbe l'ideale (grazie mille Qu@aker il tempo speso a scrivere il codice) ma purtroppo non posso cambiare il programma più di tanto, sono costretto ad utilizzare i processi creati con fork(). Pare proprio che la soluzione sia l'utilizzo di pipe() come suggerito da AnonimoVeneziano. Che asino che sono Grazie ancora
__________________
![]() |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:37.