私はオープンコースからCシェルの実装を試していますが、出力バッファリングの動作について興味深いものがあります。C言語の奇妙な出力バッファリング動作
コードは、この(私は使用線PID = waitpidを(-1、& R、WNOHANG)注意)のような行く:RUNCMD関数は次のようである
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);
}
を(内ことに注意私は2つのプロセスを作成し、それらが終了するのを待ち)を取り扱うパイプ:「LSを|ソート」
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);
}
奇妙な事は、私が実行したときに、あるターミナルで、私は常にFを取得します出力
6.828$ ls | sort
6.828$ a.out
sh.c
t.sh
をollowingこれは、次のコマンドプロンプト「6828は$」印刷される前に、子プロセスからの出力は、まだ端末にフラッシュされていないことを示しています。しかし
、私はPID = waitpidを(-1、& R、WNOHANG))を使用してPID = waitpidを(-1、& R、0))(または待機を使用していない場合は())、出力は次のように通常のようになります。
6.828$ ls | sort
a.out
sh.c
t.sh
私は長い間、問題の原因について考えてきたが、考えられる理由を思い付くしませんでした。誰かが何らかの理由を示唆できますか?
ありがとうございます!
while ((pid = waitpid(-1, &r, WNOHANG)) >= 0) {
if (errno == ECHILD) {
break;
}
}
while
ループブレークすぐwaitpid
場合は-1を返し、エラーの場合に返されます正確に何である: