提问人:Jix 提问时间:11/14/2023 更新时间:11/14/2023 访问量:36
流水线的 C 语言实现中的 Mini Shell:等待子进程问题
Mini Shell in C implementation of pipeline : wait for child process problem
问:
我一直在尝试在使用 C 构建的迷你 shell 中实现管道功能。但是我注意到,当管道包含需要等待其他进程的进程并输出到 stderr 而不是 stdout 时,效果是使管道中的下一个命令也等待。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "variante.h"
#include <sys/wait.h>
#include "readcmd.h"
#include <stdbool.h>
void execute_single_command(char **cmd){
execvp(cmd[0],cmd);
}
void execute_pipeline(struct cmdline *l){ // *head_over=head // *head - > node 1
int previous_pipe_read = -1;
int file_descriptor[2];
for(size_t i=0 ; l->seq[i] != 0; i++){
pipe(file_descriptor);
pid_t child_pid = fork();
char**cmd = l->seq[i];
if (child_pid == -1) {
perror("fork error");
exit(EXIT_FAILURE);
}
if(child_pid == 0){
// Child process
if (previous_pipe_read != -1)
{
// Redirect to the reading side of the pipe ( file_descriptor[0] ) and use it as stdint
dup2(previous_pipe_read, 0);
close(previous_pipe_read);
}
if (l->seq[i + 1] != 0)
{
// Redirect stdout to the writing side of the pipe ( file_descriptor[1] )
dup2(file_descriptor[1], 1);
}
// Close unecessary file descriptor
close(file_descriptor[0]);
// Execute command
execute_single_command(cmd);
}
else{
// Parent process
// Handle the signal received by a terminated child process
close(file_descriptor[1]); // Close unecessary file descriptor
if (previous_pipe_read != -1)
{
close(previous_pipe_read);
}
if (!l->bg)
{
int status;
waitpid(child_pid, &status, 0);
}
// save the reading side of the pipe (aka the ouput of the previous command) into the variable previous_pipe_read
previous_pipe_read = file_descriptor[0];
}
}
}
int main()
{
// unrelated code
while (1)
{
struct cmdline *l;
char *line = 0;
char *prompt = "ensishell>";
/* Readline use some internal memory structure that
can not be cleaned at the end of the program. Thus
one memory leak per command seems unavoidable yet */
line = readline(prompt);
if (line == 0 || !strncmp(line, "exit", 4))
{
terminate(line);
}
#if USE_GNU_READLINE == 1
add_history(line);
#endif
#if USE_GUILE == 1
/* The line is a scheme command */
if (line[0] == '(')
{
char catchligne[strlen(line) + 256];
sprintf(catchligne, "(catch #t (lambda () %s) (lambda (key . parameters) (display \"mauvaise expression/bug en scheme\n\")))", line);
scm_eval_string(scm_from_locale_string(catchligne));
free(line);
continue;
}
#endif
/* parsecmd free line and set it up to 0 */
l = parsecmd(&line);
/* If input stream closed, normal termination */
if (!l)
{
terminate(0);
}
if (l->err)
{
/* Syntax error, read another command */
printf("error: %s\n", l->err);
continue;
}
if (l->in)
printf("in: %s\n", l->in);
if (l->out)
printf("out: %s\n", l->out);
if (l->bg)
printf("background (&)\n");
/* Display each command of the pipe */
execute_pipeline(l);
}
}
例如:
sleep 5 | echo " Hello World"
它会等待 5 秒钟,然后回显 Hello World,这不是正确的事情。我正在反思,也许我需要检查上一个命令是否输出到 stdout 以应用管道效果。
这是我的代码:
答: 暂无答案
评论