Ich versuche, eine einfache Shell in c zu schreiben. Im Moment versuche ich, Rohre zur Arbeit zu bringen. Ich habe eine Struktur c
, die ich in diese Funktion füttere, es enthält einen Platz zum Speichern der Rohr Datei-Deskriptor pipfd
und enthält auch Informationen über die End-Tag jedes Befehls c->type
(dies kann sein | || & & & etc). CommandPrev
verfolgt nur den letzten Befehl, damit ich sehen kann, ob der Befehl unmittelbar zuvor ein Pipe-Tag hatte.Warum sprechen meine Rohre nicht miteinander?
Nachdem ich diese Funktion zu beenden, gebe ich dem Kind pid (den Wert zurück) zu waitpid
auf dem Befehl, den ich mit execvp
genannt warten
Wenn ich Befehle ausführen wie echo foo | echo bar
I bar
als Ausgang genau das bekommen, wie Ich würde erwarten und alles funktioniert super. Mein Problem ist, wenn ich versuche, einen Befehl auszuführen, der tatsächlich die Eingabe aus der ersten Hälfte der Pipe verwendet, bleibt alles hängen. Wenn ich etwas wie echo foo | wc -c
ausführen bekomme ich keine Ausgabe und es hängt einfach für immer.
Ich kann sehen, dass diese Funktion für diese Art von Befehlen beendet ist, weil ich bei der Rückkehr drucke. Was passiert, ist, dass der Befehl, den ich mit execvp anrufe, nie passiert, also wartet meine Wartezeit auf immer.
Ich denke, dass irgendwie meine Verbindung zwischen den beiden Enden meiner Pfeife gebrochen ist. Entweder werden Dinge nie geschrieben, oder sie werden nie gelesen, oder das empfangende Ende der Pipe erkennt nie, dass die Schreibseite fertig ist und wartet nur für immer. Ich rufe alle meine Pfeifen sofort an, also bezweifle ich, dass es die letzte ist ... aber ich bin mir nicht sicher, wie ich diese drei Szenarien testen soll.
Dies ist mein Code:
pid_t start_command(command* c, pid_t pgid) {
(void) pgid;
// If its a pipe token, create a shared pipe descriptor
if (c->type == TOKEN_PIPE){
pipe(c->pipefd);
}
// Fork a child process, run the command using `execvp`
pid_t child = fork();
if (child == 0) {
// writing side of the pipe
if (c->type == TOKEN_PIPE){
dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
close(c->pipefd);
}
// receiving side of the pipe
else if (commandPrev->type == TOKEN_PIPE){
dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
close(commandPrev->pipefd);
}
// run the command
if (execvp(c->argv[0], c->argv) == -1) {
// fork failed
exit(-1);
}
}
else{
// clean up, clean up, everybody, everywhere
if (commandPrev->type == TOKEN_PIPE){
close(commandPrev->pipefd);
}
}
printf("return %i\n", getpid());
return child;
}
Thank you!
Überprüfen Sie Ihre syscalls für Fehler, sie werden nicht automatisch gedruckt. 'close (c-> pipefd);' scheint zu versuchen, ein Array zu schließen. –
Verwenden Sie das 'shell'-Tag für Fragen, bei denen die Kenntnis der Shell-Spezifikationen und -Sprachen für die Beantwortung hilfreich sein kann. Das ist sehr, sehr selten wahr, wenn Leute Spielzeugmuscheln für die Schule schreiben. –
@CharlesDuffy Mein schlechtes! Ich wusste es nicht, Entschuldigung – Twiigs