c перенаправление ввода оболочки остается открытым

Я использую следующую часть кода для перенаправления ввода для моей пользовательской оболочки C ++.
Хотя перенаправление вывода, подобное этому, работает хорошо, дочерний процесс для перенаправления ввода остается открытым и не возвращается, как будто он продолжает ждать нового ввода.
Каков наилучший способ «попросить» или «заставить» дочерний процесс, подобный этому, немедленно вернуться после прочтения ввода?

Код для перенаправления ввода

int in_file = open(in, O_CREAT | O_RDONLY , S_IREAD | S_IWRITE);
pid_t pid = fork();
if (!pid) {
dup2(in_file, STDIN_FILENO);
if (execvp(argv[0], argv) < 0) {
cerr << "*** ERROR: exec failed: "<< argv[0] << endl;
exit(EXIT_FAILURE);
}
}
close(in_file);

Код для перенаправления вывода

out_file = open(out, O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU);
pid_t pid = fork();
if (!pid) {
dup2(out_file, STDOUT_FILENO);
if (execvp(argv[0], argv) < 0) {
cerr << "*** ERROR: exec failed: "<< argv[0] << endl;
exit(EXIT_FAILURE);
}
}
close(out_file);

Я использовал следующие команды для тестирования:

ps aux > out.txt
grep root < out.txt

Первая команда возвращается в оболочку после успешной записи в out.txt. Вторая команда успешно читает из out.txt, но не возвращается и не останавливается.

1

Решение

У ребенка все еще есть открытый файл in_file. Вы должны закрыть его перед exec:

dup2(in_file, STDIN_FILENO);
close(in_file);

(проверка ошибок опущена для краткости). Поскольку у дочернего элемента все еще есть дескриптор открытого файла, он никогда не видит файл как закрытый, поэтому он блокирует чтение, ожидая, когда кто-то запишет больше данных. Дочерний процесс не понимает, что именно он держит дескриптор файла открытым. Другой вариант — установить ‘Близко-на-Exec’ флаг дескриптора файла, чтобы он автоматически закрывался при запуске. (Поиск по FD_CLOEXEC)

0

Другие решения

Сначала проверьте аргументы execvp(), Если этот код является частью main(int argc, char* argv[]), затем argv[0] это ваша собственная программа, а не grep, Это означает, что ваша программа рекурсивно выполняет себя вечно.

Затем убедитесь, что нет ошибок при открытии in с:

if (in_file < 0) { perror(in); ... }

Если in_file неверный дескриптор, dup2() потерпит неудачу и grep будет запускать чтение из терминала, следовательно, не завершается. Кстати, используя O_CREAT | O_RDONLY выглядит подозрительно Зачем читать из файла, который ранее не существовал?

0

По вопросам рекламы [email protected]