|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
[RISOLTO-C]Eseguire comandi tramite processi
Ciao a tutti,
il mio non è proprio un dubbio ma una richiesta di conferma a quello che ho scritto. Se ho fatto bene o meno. Posto subito il codice: Codice:
void run_command_in_parallel_mode(struct list* cmd){
int i; //Contatore del ciclo for
pid_t pid; // Process identifier del processo generato con fork()
struct node* tmp;
tmp = cmd -> header;
char filename[50];
for(i=0; i<cmd->count; i++){ //Contatore che cicla per tutta la lunghezza della lista
pid = fork(); // Biforcazione del processo in Padre e Figlio.
if(pid==0){ // Il processo figlio è stato generato
printf("\nProcesso figlio con PID %d\tPPID %d\tVALORE DELLA i %d\tESEGUE %s\n", getpid(), getppid(), i, tmp->command);
sprintf(filename, "out.%d", i+1);
freopen( filename, "w", stdout); // Reindirizza stdout nel file destinazione
system(tmp -> command);
tmp = tmp -> next;
}else{
printf("\nProcesso padre con PID %d e PPID %d\n", getpid(), getppid());
}
}
freopen( "CON", "w", stdout ); // Ripristina stdout
}
Ora, funzionare funziona, ma non sono convinto al 100% che vada bene. Io mi faccio un for che cicla per tutta la lunghezza della lista, ad ogni ciclo faccio una biforcazione del processo con fork() e, se pid==0 vuol dire che quello è il figlio, quindi apro il file di output ed eseguo il comando con la funzione system(). Ma funziona proprio così? nel senso, è vero che i comandi vengono eseguiti in "parallelo" ognuno con un processo diverso? Oppure devo usare una funzione tipo exec per differenziare il programma che il processo esegue da quello che esegue il padre? Ultima modifica di dennis8787 : 02-10-2014 alle 16:22. |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Pertanto la Codice:
tmp = tmp->next; C'e' un altro problema simile, aspetto a dirtelo perche' magari vuoi darci un'occhiata da solo
__________________
In God we trust; all others bring data |
|
|
|
|
|
|
#3 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
Codice:
freopen( "CON", "w", stdout ); // Ripristina stdout Per fare quello che vorrei io, come dovrei farlo? Potrei, ad esempio, scrivere i comandi su un file .sh e poi farlo eseguire dal processo, quindi dentro l'if, con il comando exec? |
|
|
|
|
|
|
#4 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Quote:
In verita' il tuo algoritmo originale non sembra ottenere un gran vantaggio dal multiprocessing, poiche' la console e' una risorsa condivisa e quindi dovresti pensare a sincronizzare i processi fra di loro, in modo che accedano a questa risorsa solo uno alla volta, perdendo ogni vantaggio. A questo punto, tanto varrebbe evitare di fare la fork() ed eseguire un solo comando alla volta.
__________________
In God we trust; all others bring data |
||
|
|
|
|
|
#5 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
Per quanto riguarda, quindi, la parte di esecuzione parallela, allora vado per la scrittura e l'esecuzione di un file .sh dal processo. Semmai provo a buttar giù qualcosa e lo posto |
|
|
|
|
|
|
#6 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
Codice:
void run_command_in_parallel_mode(struct list* cmd){
int i; //Contatore del ciclo for
pid_t pid; // Process identifier del processo generato con fork()
FILE* fd;
struct node* tmp;
tmp = cmd -> header;
//char filename[50];
for(i=0; i<cmd->count; i++){ //Contatore che cicla per tutta la lunghezza della lista
pid = fork(); // Biforcazione del processo in Padre e Figlio.
if(pid==0){ // Il processo figlio è stato generato
//printf("\nProcesso figlio con PID %d\tPPID %d\tVALORE DELLA i %d\tESEGUE %s\n", getpid(), getppid(), i, tmp->command);
fd = fopen("prova.sh", "w+e");
fprintf(fd, "#!/bin/bash\n");
chmod("prova.sh", S_IRWXU);
fprintf(fd, "%s > out.%d", tmp->command, i);
/*sprintf(filename, "out.%d", i+1);
freopen( filename, "w", stdout); // Reindirizza stdout nel file destinazione
system(tmp -> command);*/
fclose(fd);
execv("./prova.sh", NULL);
printf("Questa non viene stampata!\n");
tmp = tmp -> next;
//fclose(fd);
}else{
//printf("\nProcesso padre con PID %d e PPID %d\n", getpid(), getppid());
}
}
//freopen( "CON", "w", stdout ); // Ripristina stdout
}
|
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
L'avanzamento deve essere fatto nel processo padre.
Altra cosa: una volta che il processo figlio ha finito il suo lavoro, non deve riprendere a fare il ciclo, bensi' deve morire. UCCIDILO! (una exit() e' sufficiente)
__________________
In God we trust; all others bring data |
|
|
|
|
|
#8 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
Codice:
tmp=tmp->next; Codice:
exit(0); |
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Codice:
FILE* fd;
struct node* tmp;
tmp = cmd -> header;
//char filename[50];
for(i=0; i<cmd->count; i++){ //Contatore che cicla per tutta la lunghezza della lista
pid = fork(); // Biforcazione del processo in Padre e Figlio.
if(pid==0){ // Il processo figlio è stato generato
//printf("\nProcesso figlio con PID %d\tPPID %d\tVALORE DELLA i %d\tESEGUE %s\n", getpid(), getppid(), i, tmp->command);
fd = fopen("prova.sh", "w+e");
__________________
In God we trust; all others bring data |
|
|
|
|
|
|
#10 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
|
|
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Ad ogni modo, tutti i figli cercheranno di aprire lo stesso file, visto che il nome e' fisso. Immagino non sia quello che vuoi fare....
__________________
In God we trust; all others bring data |
|
|
|
|
|
|
#12 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
Quello che vorrei è che ogni processo crea il file "prova.sh" con dentro il comando da eseguire, e lo esegue. Ogni processo deve creare, e poi eseguire, il proprio file .sh. EDIT: Quello che ottengo da questo codice Codice:
for(i=0; i<cmd->count; i++){ //Contatore che cicla per tutta la lunghezza della lista
/*fd = fopen("prova.sh", "w");
fprintf(fd, "#!/bin/bash\n");
chmod("prova.sh", S_IRWXU);*/
pid = fork(); // Biforcazione del processo in Padre e Figlio.
if(pid==0){ // Il processo figlio è stato generato
//printf("\nProcesso figlio con PID %d\tPPID %d\tVALORE DELLA i %d\tESEGUE %s\n", getpid(), getppid(), i, tmp->command);
fd = fopen("prova.sh", "w+");
fprintf(fd, "#!/bin/bash\n");
int d = chmod("prova.sh", S_IRWXU);
if(d==0){
printf("Permessi di esecuzione dati!\n");
}else{
printf("Permessi di esecuzione non dati!\n");
}
fprintf(fd, "%s > out.%d", tmp->command, i);
/*sprintf(filename, "out.%d", i+1);
freopen( filename, "w", stdout); // Reindirizza stdout nel file destinazione
system(tmp -> command);*/
//fclose(fd);
execv("./prova.sh", NULL);
//tmp = tmp -> next;
fclose(fd);
exit(0);
Ultima modifica di dennis8787 : 01-10-2014 alle 10:21. |
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Intendevo che il file "prova.sh", essendo unico ed essendo creato e scritto contemporaneamente da tutti i processi, ti puo' dare problemi.
Potresti decidere di usare un file diverso per ogni processo. Una volta corretto questo potresti fare un giro di debug o magari cominciare a stampare un po' di valori, per vedere come vanno le cose. Probabilmente potresti partire da una lista con un solo valore, cosi' da creare un solo processo e vedere se lui funziona. Un'altra cosa: scusa l'ignoranza ma per ridirigere l'output ho sempre usato la dup(), i.e. qualcosa del tipo Codice:
inFile = open(filename_in, O_RDONLY, 0); inDup = dup2(inFile, STDIN_FILENO); close(inFile); outFile = creat(filename_out, 0644); outDup = dup2(outFile, STDOUT_FILENO); close(outFile);
__________________
In God we trust; all others bring data |
|
|
|
|
|
#14 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
Ma, come faccio a crearmi un file diverso per ogni processo in esecuzione? |
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
freopen( filename, "w", stdout); // Reindirizza stdout Per creare un file diverso per ogni processo potresti, per esempio, ottenere il process id del figlio mediante la funzione getpid() ed usarlo nel nome del file. (Poi suggerirei anche di pensare ad un modo per cancellarli, visto che dopo un po' di prove ti troverai un sacco di questi file)
__________________
In God we trust; all others bring data |
|
|
|
|
|
|
#16 | |
|
Member
Iscritto dal: Apr 2011
Messaggi: 80
|
Quote:
Forse sono arrivato ad un dunque, con questo codice, che sembra funzionare Codice:
void run_command_in_parallel_mode(struct list* cmd){
int i; //Contatore del ciclo for
pid_t pid; // Process identifier del processo generato con fork()
FILE* fd = 0;
struct node* tmp;
tmp = cmd -> header;
char filename[50];
for(i=0; i<cmd->count; i++){ //Contatore che cicla per tutta la lunghezza della lista
/*fd = fopen("prova.sh", "w+");
fprintf(fd, "#!/bin/bash\n");
chmod("prova.sh", S_IRWXU);*/
pid = fork(); // Biforcazione del processo in Padre e Figlio.
if(pid==0){ // Il processo figlio è stato generato
//printf("\nProcesso figlio con PID %d\tPPID %d\tVALORE DELLA i %d\tESEGUE %s\n", getpid(), getppid(), i, tmp->command);
sprintf(filename, "processo%d.sh", getpid());
fd = fopen(filename, "w+");
fprintf(fd, "#!/bin/bash\n");
int d = chmod(filename, S_IRWXU);
if(d==0){
printf("Permessi di esecuzione dati!\n");
}else{
printf("Permessi di esecuzione NON dati!\n");
}
fprintf(fd, "%s > out.%d", tmp->command, i);
/*sprintf(filename, "out.%d", i+1);
freopen( filename, "w", stdout); // Reindirizza stdout nel file destinazione
system(tmp -> command);*/
fclose(fd);
execv(filename, NULL);
//tmp = tmp -> next;
//fclose(fd);
exit(0);
}else{
//fclose(fd);
tmp = tmp -> next;
//printf("\nProcesso padre con PID %d e PPID %d\n", getpid(), getppid());
}
//fclose(fd);
}
//freopen( "CON", "w", stdout ); // Ripristina stdout
}
Che ne pensi? EDIT: No, mettere system("rm p*"); nel main prima della terminazione del programma non va bene perchè il programma principale termina prima che i processo finiscano il loro compito, in questo modo si cancellerebbero file ancora da eseguire, mandando in errore il programma Ultima modifica di dennis8787 : 01-10-2014 alle 12:35. |
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Allora... per prima cosa correggo un mio errore: ti ho detto di mettere la exit(0) per essere sicuro che il processo figlio finisca, ma non mi ero accorto che c'era una exec() in mezzo, e dalla exec() non si torna.
Pertanto la exit() e' ridondante, non la eseguirai mai. scusami. Ho controllato il tuo codice: congratulazioni! Mi sembra che sia ottimo. Per quanto riguarda la cancellazione dei file, potresti aspettare, nel tuo programma principale, che tutti i processi che hai forkato abbiano completato l'esecuzione prima di cancellare i file. Per farlo, puoi usare la wait() o la waitpid(). Il manuale di queste istruzioni lo puoi trovare nelle man page del tuo sistema, oppure qui: http://linux.die.net/man/3/wait
__________________
In God we trust; all others bring data |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:38.




















