Я пытаюсь связаться с внешней программой, которая, если она будет выполнена, запустит терминальный интерфейс. Обычно мне нужно предоставить некоторые входные данные (например, 1 + 1), а затем прочитать вывод программы (например, 2). Поскольку мне нужна двусторонняя связь, я не смог использовать popen().
Моя проблема заключается в следующем:
Всякий раз, когда у меня есть часть кода, которая запрашивает ввод, например, содержащая std::cin >> input
, я сталкиваюсь с той же проблемой, команда read
никогда не завершается.
Здесь я написал минимальный пример, все, что делает дочерний процесс, это читает ввод и повторяет его.
Когда я пытаюсь запустить этот код, происходит то, что я вижу первую печать Родитель говорит: и я могу предоставить ввод и отправить его, используя write
. Однако, когда я пытаюсь снова вызвать функцию read()
, чтобы увидеть результат, она никогда не выходит.
Я заметил, что если закрыть канал, идущий от родителя к дочернему (fd_p2c[1]
), то я могу успешно читать. Это явно не то, что я хочу, так как в моем приложении я хотел бы сохранить оба сообщения открытыми.
Любые предложения о том, что можно сделать, чтобы решить эту проблему?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
int status, buf_length;
// Input and output
char buf[256];
char msg[256];
char child_read[256];
int fd_c2p[2]; // file descriptor pipe child -> parent
int fd_p2c[2]; // file descriptor pipe parent -> child
pipe(fd_c2p);
pipe(fd_p2c);
// Spawn a new process with pid
pid_t pid = fork(); // Fork process
if (pid == 0) {
// Child
// Close the unused end of the pipe
if (close(fd_p2c[1]) != 0 || close(fd_c2p[0]) != 0) {
fprintf(stderr, "Faild to close unused end of pipe\n");
exit(1);
}
// Set the comunication
if (dup2(fd_p2c[0], STDIN_FILENO) != 0 ||
dup2(fd_c2p[1], STDOUT_FILENO) != 1 ||
dup2(fd_c2p[1], STDERR_FILENO) != 2) {
fprintf(stderr, "Faild to duplicate the end of the pipes\n");
exit(1);
}
// These two pipe ends are not needed anymore
if (close(fd_p2c[0]) != 0 || close(fd_c2p[1]) != 0) {
fprintf(stderr, "Faild to close unused end of pipe\n");
exit(1);
}
// ask kernel to deliver SIGTERM in case the parent dies
prctl(PR_SET_PDEATHSIG, SIGTERM);
// Moch program
while (1) {
fprintf(stdout, "Parent says: ");
fflush(stdout);
scanf("%s", child_read);
fprintf(stdout, " >> Child repeat: %s\n", child_read);
fflush(stdout);
}
exit(1);
} else {
// Parent
// These two pipe ends are not needed anymore
if (close(fd_p2c[0]) != 0 || close(fd_c2p[1]) != 0) {
fprintf(stderr, "Faild to close unused end of pipe\n");
exit(1);
}
}
// Read output and send input
while (1) {
// Read from child
while (buf_length = read(fd_c2p[0], buf, sizeof(buf) - 1)) {
buf[buf_length] = '\0';
printf("%s", buf);
}
// Enter message to send
scanf("%s", msg);
if (strcmp(msg, "exit") == 0)
break;
// Send to child
write(fd_p2c[1], msg, strlen(msg));
//close(fd_p2c[1]);
}
printf("KILL");
kill(pid, SIGKILL); // send SIGKILL signal to the child process
waitpid(pid, &status, 0);
}
while (buf_length = read(fd_c2p[0], buf, sizeof(buf) - 1))
имеет один фатальный недостаток: еслиread
не работает, вы не обнаружите его и сразу же запишете за пределы массиваbuf
. - person Some programmer dude   schedule 03.02.2021dup2(fd_c2p[1], STDOUT_FILENO) != 1 || dup2(fd_c2p[1], STDERR_FILENO) != 2) {
похоже, это ошибка - person user3629249   schedule 06.02.2021