在 c 中支持 shell 的管道
supporting pipes for shell in c
对于 class,我需要在 C 中创建自己的 shell。
我正在尝试使用管道支持命令管道。据我所知,管道的两端都关闭了。尽管如此,我还是没有得到任何结果,有人能发现这里出了什么问题吗?
do_* 函数是带有微小错误处理包装器的函数。为了完整起见,它们包含在页面底部。
此函数生成一个程序并确保子程序只能读取和写入正确的管道。
int execute_piped_binairy (int input, int output, Pgm *program){
pid_t pid = do_fork();
if (pid == 0){ //I am the child
if (input != 0){//input is not standard input, overwrite stdin with given input
do_dub_and_close(input, 0);
} if (output != 1) { //output is not standard output, overwrite stdout with given output
do_dub_and_close(output, 1);
}
do_exec(program->pgmlist);
} else {
return pid;
}
}
此函数生成 k 个子项和 k-1 个管道以执行 k 个命令。命令以相反的顺序给出,这意味着第一个命令应该输出到全局输出。
int execute_binairy_list (int input, int output, int pgmCount, Pgm *program){
int childPids[pgmCount];
int childStatus[pgmCount];
int childId;
int idx;
// For k programs we need k-1 pipes and need to spawn k children
for(idx = 0; idx<pgmCount-1; idx++){
int file_descriptors[2]={0, 1};
//create unnamed pipe
do_pipe(file_descriptors);
// pass stored input and created write file descriptor
childId = do_execute_piped_binairy (file_descriptors[0], output, program+idx);
childPids[idx]=childId; //keep child id to make parent wait for all children.
if(output!=1){
do_close(output);
};
do_close(file_descriptors[0]); // close read end of new pipe, child reads from this pipe.
output = file_descriptors [1]; //store write end of new pipe for next iteration
}
//we still need to spawn 1 child to execute the first command based on the global input
// pass stored input and created write file descriptor
childId = do_execute_piped_binairy (input, output, program+idx);
childPids[idx]=childId; //keep child id to make parent wait for all children.
if(output!=1){
do_close(output);
};
for(idx=0; idx<pgmCount; idx++){
do_wait(childPids[idx], childStatus+idx); //wait for all children to return;
}
return 0;
}
我已经用三个命令测试了我的代码,希望结果应该是这样的:
命令 1 -> 管道 1 -> 命令 2 -> 管道 2 -> 命令 3
当 运行 有很多 printfs 时会发生这种情况(或多或少因为调度会影响顺序):
created pipe: 3 4 //pipe 2
created child: 2452 //command 3
closed input: 3 //parent closes read end of pipe 2
created pipe: 3 5 //pipe 1
child: 2452 3 1 //command 3 reads from read end of pipe 2 and writes to 1
closed input: 3 2452 //command 3 closes read end of pipe 2
created child: 2453 //command 2
closed output: 4 //parent closes write end of pipe 2
closed input: 3 //parent closes read end of pipe 1
closed output: 5 //parent closes write end of pipe 1
child: 2453 3 4 //command 2 reads from read end of pipe 1 and writes to write end of pipe 2
closed input: 3 2453 //command 2 closes read end of pipe 1
closed output: 4 2453 //command 2 closes write end of pipe 2
child: 2454 0 5 //command 1 reads from 0 and writes to write end of pipe 1
closed output: 5 2454 //command 1 closes write end of pipe 1
非常感谢任何帮助
我自己想出来了。分叉时 children 从他们的 parent 接收管道两端的副本。由于 children 只关闭他们使用的一端,所以管道的一个写端总是没有关闭。这意味着永远不会发送 eof 消息
对于 class,我需要在 C 中创建自己的 shell。 我正在尝试使用管道支持命令管道。据我所知,管道的两端都关闭了。尽管如此,我还是没有得到任何结果,有人能发现这里出了什么问题吗?
do_* 函数是带有微小错误处理包装器的函数。为了完整起见,它们包含在页面底部。
此函数生成一个程序并确保子程序只能读取和写入正确的管道。
int execute_piped_binairy (int input, int output, Pgm *program){
pid_t pid = do_fork();
if (pid == 0){ //I am the child
if (input != 0){//input is not standard input, overwrite stdin with given input
do_dub_and_close(input, 0);
} if (output != 1) { //output is not standard output, overwrite stdout with given output
do_dub_and_close(output, 1);
}
do_exec(program->pgmlist);
} else {
return pid;
}
}
此函数生成 k 个子项和 k-1 个管道以执行 k 个命令。命令以相反的顺序给出,这意味着第一个命令应该输出到全局输出。
int execute_binairy_list (int input, int output, int pgmCount, Pgm *program){
int childPids[pgmCount];
int childStatus[pgmCount];
int childId;
int idx;
// For k programs we need k-1 pipes and need to spawn k children
for(idx = 0; idx<pgmCount-1; idx++){
int file_descriptors[2]={0, 1};
//create unnamed pipe
do_pipe(file_descriptors);
// pass stored input and created write file descriptor
childId = do_execute_piped_binairy (file_descriptors[0], output, program+idx);
childPids[idx]=childId; //keep child id to make parent wait for all children.
if(output!=1){
do_close(output);
};
do_close(file_descriptors[0]); // close read end of new pipe, child reads from this pipe.
output = file_descriptors [1]; //store write end of new pipe for next iteration
}
//we still need to spawn 1 child to execute the first command based on the global input
// pass stored input and created write file descriptor
childId = do_execute_piped_binairy (input, output, program+idx);
childPids[idx]=childId; //keep child id to make parent wait for all children.
if(output!=1){
do_close(output);
};
for(idx=0; idx<pgmCount; idx++){
do_wait(childPids[idx], childStatus+idx); //wait for all children to return;
}
return 0;
}
我已经用三个命令测试了我的代码,希望结果应该是这样的: 命令 1 -> 管道 1 -> 命令 2 -> 管道 2 -> 命令 3 当 运行 有很多 printfs 时会发生这种情况(或多或少因为调度会影响顺序):
created pipe: 3 4 //pipe 2
created child: 2452 //command 3
closed input: 3 //parent closes read end of pipe 2
created pipe: 3 5 //pipe 1
child: 2452 3 1 //command 3 reads from read end of pipe 2 and writes to 1
closed input: 3 2452 //command 3 closes read end of pipe 2
created child: 2453 //command 2
closed output: 4 //parent closes write end of pipe 2
closed input: 3 //parent closes read end of pipe 1
closed output: 5 //parent closes write end of pipe 1
child: 2453 3 4 //command 2 reads from read end of pipe 1 and writes to write end of pipe 2
closed input: 3 2453 //command 2 closes read end of pipe 1
closed output: 4 2453 //command 2 closes write end of pipe 2
child: 2454 0 5 //command 1 reads from 0 and writes to write end of pipe 1
closed output: 5 2454 //command 1 closes write end of pipe 1
非常感谢任何帮助
我自己想出来了。分叉时 children 从他们的 parent 接收管道两端的副本。由于 children 只关闭他们使用的一端,所以管道的一个写端总是没有关闭。这意味着永远不会发送 eof 消息