Я использую следующую часть кода для перенаправления ввода для моей пользовательской оболочки 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, но не возвращается и не останавливается.
У ребенка все еще есть открытый файл in_file. Вы должны закрыть его перед exec:
dup2(in_file, STDIN_FILENO);
close(in_file);
(проверка ошибок опущена для краткости). Поскольку у дочернего элемента все еще есть дескриптор открытого файла, он никогда не видит файл как закрытый, поэтому он блокирует чтение, ожидая, когда кто-то запишет больше данных. Дочерний процесс не понимает, что именно он держит дескриптор файла открытым. Другой вариант — установить ‘Близко-на-Exec’ флаг дескриптора файла, чтобы он автоматически закрывался при запуске. (Поиск по FD_CLOEXEC)
Сначала проверьте аргументы execvp()
, Если этот код является частью main(int argc, char* argv[])
, затем argv[0]
это ваша собственная программа, а не grep
, Это означает, что ваша программа рекурсивно выполняет себя вечно.
Затем убедитесь, что нет ошибок при открытии in
с:
if (in_file < 0) { perror(in); ... }
Если in_file
неверный дескриптор, dup2()
потерпит неудачу и grep
будет запускать чтение из терминала, следовательно, не завершается. Кстати, используя O_CREAT | O_RDONLY
выглядит подозрительно Зачем читать из файла, который ранее не существовал?