Я пишу свою собственную оболочку для домашнего задания и сталкиваюсь с проблемами.
Моя программа-оболочка получает входные данные cat scores | grep 100
из консоли и печатает выходные данные, как и ожидалось, но команда grep
не завершается, и я вижу, как она работает бесконечно из команды ps
.
EDIT. При закрытии fds произошла ошибка. Теперь команда grep не выполняется, а вывод консоли -
grep: (стандартный ввод): Неверный файловый дескриптор
Я читаю количество команд из консоли, создаю необходимые каналы и сохраняю их в двумерном int array fd[][]
перед разветвлением первого процесса.
fd[0][0]
будет содержать конец чтения 1-го канала, а fd[0][1]
будет содержать конец записи 1-го канала. fd[1][0]
будет содержать конец 2-го канала для чтения, а fd[1][1]
будет содержать конец 2-го канала для записи и так далее.
Каждый новый процесс дублирует свой stdin
с концом чтения своего канала с предыдущим процессом и дублирует свой stdout
с концом записи своего канала со следующим процессом.
Ниже моя функция:
void run_cmds(char **args, int count,int pos)
{
int pid,status;
pid = fork();
if ( pid == 0 )
{
if(pos != 0) dup2(fd[pos-1][0],0); // not changing stdin for 1st process
if(pos != count) dup2(fd[pos][1],1); //not changing stdout for last process
close_fds(pos);
execvp(*args,args);
}
else
{
waitpid(pid,&status,0);
count--;
pos++;
//getting next command and storing it in args
if(count > 0)
run_cmds(args,count,pos);
}
}
}
- args будет содержать аргументы команды.
- count — это количество команд, которые мне нужно создать.
- pos — позиция команды во входных данных.
Я не могу понять проблему. Я использовал этот же подход для жестко закодированных значений до этого, и он работал.
Чего мне не хватает в моем понимании/реализации dup2
/fork
и почему команда ждет бесконечно?
Любые материалы будут очень полезны. Поразил этим за последние пару дней!
РЕДАКТИРОВАТЬ: функция close_fds() выглядит следующим образом: для любого процесса я закрываю оба канала, связывающие процесс.
void close_fds(int pos)
{
if ( pos != 0 )
{
close(fd[pos-1][0]);
close(fd[pos-1][1]);
}
if ( pos != count)
{
close(fd[pos][0]);
close(fd[pos][1]);
}
}
fork
,waitpid
,dup2
,execvp
). Если они возвращают код ошибки, используйтеperror
илиstrerror(errno)
, чтобы распечатать ошибку. Пожалуйста, обновите вопрос, указав, что ошибок не было. Пожалуйста, вызовитеabort();
послеexecvp
, чтобы убедиться, что дочерний процесс не продолжит работу. - person pts   schedule 11.10.2014