Ich probiere eine C-Shell-Implementierung aus einem offenen Kurs aus, doch es gibt etwas Faszinierendes am Verhalten der Ausgabepufferung.Seltsames Ausgabepufferverhalten in C
Der Code lautet wie folgt (beachten Sie die Zeile, wo ich verwenden pid = waitpid (-1, & r, WNOHANG)):
int
main(void)
{
static char buf[100];
int fd, r;
pid_t pid = 0;
// Read and run input commands.
while(getcmd(buf, sizeof(buf)) >= 0){
if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
buf[strlen(buf)-1] = 0; // chop \n
if(chdir(buf+3) < 0)
fprintf(stderr, "cannot cd %s\n", buf+3);
continue;
}
if((pid = fork1()) == 0)
runcmd(parsecmd(buf));
while ((pid = waitpid(-1, &r, WNOHANG)) >= 0) {
if (errno == ECHILD) {
break;
}
}
}
exit(0);
}
Die runcmd Funktion wie folgt ist (das in beachten Rohrhandhabungs I erstellen 2 Prozesse Kind und warten, bis sie) beenden:
void
runcmd(struct cmd *cmd)
{
int p[2], r;
struct execcmd *ecmd;
struct pipecmd *pcmd;
struct redircmd *rcmd;
if(cmd == 0)
exit(0);
switch(cmd->type){
case ' ':
ecmd = (struct execcmd*)cmd;
if(ecmd->argv[0] == 0) {
exit(0);
}
// Your code here ...
// fprintf(stderr, "starting to run cmd: %s\n", ecmd->argv[0]);
execvp(ecmd->argv[0], ecmd->argv);
fprintf(stderr, "exec error !\n");
exit(-1);
break;
case '>':
case '<':
rcmd = (struct redircmd*)cmd;
// fprintf(stderr, "starting to run <> cmd: %s\n", rcmd->file);
// Your code here ...
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
if (rcmd->type == '<') {
// input
close(0);
if (open(rcmd->file, O_RDONLY, mode) != 0) {
fprintf(stderr, "Opening file error !\n");
exit(-1);
}
} else {
// output
close(1);
if (open(rcmd->file, O_WRONLY|O_CREAT|O_TRUNC, mode) != 1) {
fprintf(stderr, "Opening file error !\n");
exit(-1);
}
}
runcmd(rcmd->cmd);
break;
case '|':
pcmd = (struct pipecmd*)cmd;
// fprintf(stderr, "starting to run pcmd\n");
// Your code here ...
pipe(p);
if (fork1() == 0) {
// child for read, right side command
close(0);
if (dup(p[0]) != 0) {
fprintf(stderr, "error when dup !\n");
exit(-1);
}
close(p[0]);
close(p[1]);
runcmd(pcmd->right);
fprintf(stderr, "exec error !\n");
}
if (fork1() == 0) {
// left side command for writing
close(1);
if (dup(p[1]) != 1) {
fprintf(stderr, "dup error !\n");
exit(-1);
}
close(p[0]);
close(p[1]);
runcmd(pcmd->left);
fprintf(stderr, "exec error !\n");
}
close(p[0]);
close(p[1]);
int stat;
wait(&stat);
wait(&stat);
break;
default:
fprintf(stderr, "unknown runcmd\n");
exit(-1);
}
exit(0);
}
die wierd Sache ist, wenn ich "ls | Art" execute im Terminal, bekomme ich ständig die f Dieser Ausgang ach
6.828$ ls | sort
6.828$ a.out
sh.c
t.sh
zeigt an, dass, bevor die nächste Eingabeaufforderung „6828 $“ gedruckt wird, wird die Ausgabe von dem Kindprozess immer noch nicht mit dem Anschluß gespült.
Allerdings, wenn ich nicht verwenden pid = waitpid (-1, & r, WNOHANG)) und verwenden pid = waitpid (-1, & r, 0)) (oder wait()), wäre der Ausgang normal wie:
6.828$ ls | sort
a.out
sh.c
t.sh
ich habe für eine lange Zeit über die Ursache des Problems gedacht, aber mit einem möglichen Grunde nicht kommen. Kann jemand einen möglichen Grund vorschlagen?
Vielen Dank!