Un'assegnazione nella mia classe Sistemi operativi mi richiede di costruire un albero di processo binario chiamando recursivamente exec sullo stesso programma. L'obiettivo è dividere alcune attività arbitrarie in processi separati. Il genitore dovrebbe comunicare con i bambini e i figli con il genitore solo tramite pipe senza nome. L'idea è che il genitore manda ogni bambino a metà del lavoro e questo continua in modo ricorsivo fino a quando viene raggiunto un caso base in cui la lunghezza della stringa passata a ogni bambino è < = 2. Il bambino quindi elabora questi dati e li restituisce i risultati al genitore tramite pipe.Tubo, forcella ed Exec - Comunicazione bidirezionale tra processo padre e figlio
Per una migliore comprensione di come la comunicazione bidirezionale funziona con le tubazioni in c ho creato il seguente programma semplice prima di passare all'assegnazione effettiva. Tuttavia, il genitore non legge mai i dati dal processo figlio. Mi aspetto l'uscita ...
nel genitore | messaggio ricevuto: prova
Invece, quando stampo ricevo ...
in superiore | messaggio ricevuto:
Sembra che il buff sia vuoto e non stia leggendo dal processo figlio. Qualcuno può spiegare quello che sto facendo male e/o il modo standard di
- scrivendo a exec'd bambino da genitori
- lettura da genitore a figlio exec'd
- iscritto a padre da bambino exec'd
- lettura da bambino exec'd nel genitore
sono tenuto a utilizzare exec(), pipe(), fork(). Grazie.
/**
* *********************************
* two_way_pipes.c
* *********************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define PARENT_READ read_pipe[0]
#define PARENT_WRITE write_pipe[1]
#define CHILD_WRITE read_pipe[1]
#define CHILD_READ write_pipe[0]
#define DEBUGGING 1
int main(int argc, char **argv) {
char buff[5];
// in the child process that was exec'd on the orginal call to two_way_pipes
if(argc == 2) {
read(STDIN_FILENO, buff, 4); // this should read "test" from stdin
buff[4] = '\0';
fprintf(stdout, "%s\n", buff); // this should right "test" to stdout and be read by the parent process
// int the root process, the original call to two_way_pipes with no args
} else {
int pid;
int read_pipe[2];
int write_pipe[2];
pipe(read_pipe);
pipe(write_pipe);
pid = fork();
// parent process
if(pid > 0) {
close(CHILD_READ);
close(CHILD_WRITE);
write(PARENT_WRITE, "test", 4); // attempting to write this to the child
struct timeval tv;
fd_set readfds;
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(PARENT_READ, &readfds);
select(PARENT_READ + 1, &readfds, NULL, NULL, &tv);
if(FD_ISSET(PARENT_READ, &readfds)) {
read(PARENT_READ, buff, 4); // should read "test" which was written by the child to stdout
buff[4] = '\0';
close(PARENT_READ);
close(PARENT_WRITE);
fprintf(stderr, "in parent | message received: %s\n", buff); // "test" is not in buff
}
// child process
} else if(pid == 0) {
close(PARENT_READ);
close(PARENT_WRITE);
dup2(CHILD_READ, STDIN_FILENO);
dup2(CHILD_WRITE, STDOUT_FILENO);
close(CHILD_READ);
close(CHILD_WRITE);
char *argv2[] = {"some random arg to make sure that argc == 2 in the child", NULL};
execvp("two_way_pipes", argv2);
_exit(0);
// error forking child process
} else {
fprintf(stderr, "error forking the child\n");
}
}
}
Aggiornamento
in base alla risposta di Jonathon ho modificato la matrice arg2 essere passato nel execvp a ...
char *argv2[] = {"two_way_pipes", "1", NULL};
execvp("two_way_pipes", argv2);
Questo non risolvere il problema. Il genitore non era ancora in grado di leggere "test" dal client. Tuttavia, in risposta alla risposta di Jonathon e al commento di William, ho iniziato a modificare la mia chiamata exec e, per qualche motivo, cambiarla con la linea show sotto funzionante.
execl("two_way_pipes", "two_way_pipes", "1", NULL);
Accetterò volentieri tutte le risposte che spiegano il motivo per cui la chiamata execvp non avrebbe funzionato, ma la chiamata execl ha fatto.
Il tuo exevp ha avuto successo?Prova a sostituire _exit (0) con 'perror (" execvp ")' –
Grazie William. Ho sostituito la chiamata _exit (0) con perror ("execvp"). Quel messaggio di errore non è mai stato stampato, ma ho iniziato a modificare la mia chiamata exec e per qualche motivo cambiando la chiamata a execl ("two_way_pipes", "two_way_pipes", "1", NULL); risolto il problema –
Questo codice manca di conseguenza per verificare l'esito delle chiamate di sistema. In caso contrario, il testing e il debug sono difficili e il programma è debole. Per favore vedi la mia risposta. – alk