Я написал bash как Linux оболочку в C.
(Ссылка на мой репозиторий: https://github.com/oneiro-naut/wish. Файл src/execute.c
имеет файл execute_pipeline функция в нем)
У меня проблема с реализацией встроенных команд, которые производят некоторый вывод. Встроенные функции, которые не выдают никаких результатов, например cd
и exit
, работают просто отлично. Внешние команды работают без сбоев. В Shell есть поддержка конвейерных конструкций и перенаправление ввода / вывода. Проблема в том, что я пытаюсь запустить внутреннюю команду (которая просто печатает сообщение). Когда я перенаправляю вывод встроенной команды в команду grep, используя канал, дочерний процесс grep зависает, что, как мне кажется, происходит, потому что grep никогда не встречает конец потока (или EOF) при чтении из канала.
ПРИМЕЧАНИЕ. не происходит, когда в конвейере есть только внешние команды. (Я позаботился о том, чтобы ни одна (внешняя) команда не завершилась до того, как следующая команда еще не запущена, поэтому она там не зависает)
Вот упрощенная версия моей проблемы `
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
int main()
{
int pipe_fd[2] = {-1,-1};
int EXIT_STAT = 0;
pipe(pipe_fd);//creating pipe
char* argv[]={"grep","Radiohead",NULL};
int std_out_dup = dup(1);
dup2(pipe_fd[1],1); // redirecting stdout to parent pipe's read end
//close(pipe_fd[0]);//closing parent pipe's write end
printf("Alice in Chains\n");
printf("Radiohead\n");
printf("Dinosaur Jr.\n");
printf("Pixies\n");
printf("Soundgarden\n");
printf("Porcupine Tree\n");
printf("Pain of Salvation\n");
pid_t pid = fork();
if(pid == 0)//child process
{
dup2(pipe_fd[0],0); //redirecting grep's stdin to parent pipe's write end
close(pipe_fd[1]);
execvp(argv[0],argv);//executing grep command
perror("\n");
exit(-1);
}
else if(pid > 0)//parent process
{
int i;//closing pipes for parent
for(i=0;i<2;i++)
close(pipe_fd[i]);
do{ // waiting for grep to exit
waitpid(pid,&EXIT_STAT,WUNTRACED);
//write(,"\x4",1);
}while(!WIFEXITED(EXIT_STAT)&&!WIFSIGNALED(EXIT_STAT));
}
else ;//fork error
dup2(std_out_dup,1); // restore stdout fd for parent process
return 0;
}
`
Программа зависает, если я пытаюсь запустить ее, ничего не печатая. Но нажатие ^ D завершает программу, производящую вывод:
Alice in Chains
Radiohead
Dinosaur Jr.
Pixies
Soundgarden
Porcupine Tree
Pain of Salvation
Так что кажется, что grep не может читать бесконечно, потому что не получает никакого сигнала EOF. Пожалуйста, укажите мои ошибки, я действительно запутался.
РЕДАКТИРОВАТЬ: Теперь даже нажатие ^ D не прекращается, поэтому мне нужно просто ^ C программы.
ПРОГРАММА ПОСЛЕ ИСПРАВЛЕНИЯ:
int main()
{
int pipe_fd[2] = {-1,-1};
int EXIT_STAT = 0;
pipe(pipe_fd);//creating pipe
char* argv[]={"grep","Radiohead",NULL};
int std_out_dup = dup(1);
//printf("%d \n",std_out_dup);
dup2(pipe_fd[1],1); // redirecting stdout to parent pipe's read end
//close(pipe_fd[0]);//closing parent pipe's write end
printf("Alice in Chains\n");
printf("Radiohead\n");
printf("Dinosaur Jr.\n");
printf("Pixies\n");
printf("Soundgarden\n");
printf("Porcupine Tree\n");
printf("Pain of Salvation\n");
fflush(stdout);
pid_t pid = fork();
if(pid == 0)//child process
{
close(pipe_fd[1]);
dup2(pipe_fd[0],0); //redirecting grep's stdin to parent pipe's write end
dup2(std_out_dup,1); // restore stdout fd for parent process
execvp(argv[0],argv);//executing grep command
perror("\n");
exit(-1);
}
else if(pid > 0)//parent process
{
int i;//closing pipes for parent
for(i=0;i<2;i++)
close(pipe_fd[i]);
dup2(std_out_dup,1); // restore stdout fd for parent process
do{ // waiting for grep to exit
waitpid(pid,&EXIT_STAT,WUNTRACED);
}while(!WIFEXITED(EXIT_STAT)&&!WIFSIGNALED(EXIT_STAT));
}
else ;//fork error
return 0;
}