связь с программой execv() через канал не работает

я пытаюсь написать сокет, который загружает программы и перенаправляет сокет io на них. звучит очень похоже на inetd, но, насколько я знаю, inetd загружает программу, когда запрашивается ее порт. Я хочу, чтобы он загружался постоянно.

Все идет нормально. написать сервер сокетов не так сложно, но у меня не получилось работать с остальными. В основном я хочу открыть pipe(), dup2() для stdin и stdout и execv() моей программы.

проблема в том, что моя вызываемая программа не получает никаких входных данных. Я попытаюсь показать это с помощью тестовой программы. может кто-нибудь сказать мне, что не так?

int create_program_fork(int *ios, char const *program) { 
// create pipes to program 
if (pipe(ios) != 0) { 
    return -1; 
} 

// fork to new process 
int f = fork(); 
if (f < 0) { 
    // fork didn't work 
    close(ios[0]); 
    close(ios[1]); 
    return(-1); 
} 
if (f > 0) { 
    // master hasn't much to do here 
    return f; 
} 
// *** Child Process 
// close std** file descriptors 
printf ("executing program"); 
close(STDIN_FILENO); 
close(STDOUT_FILENO); 
// duplicate pipes as std** 
dup2(ios[0], STDIN_FILENO); 
dup2(ios[1], STDOUT_FILENO); 
// close pipes 
close(ios[0]); 
close(ios[1]); 
// call program 
return execvp(program, NULL ); 
} 

int main(int argc, char *argv[]) { 
int ios[2]; 

// call program 
int pid = create_program_fork(ios, "/bin/bash"); 
if (0 != pid){ 
    exit(EXIT_FAILURE); 
} 

char const exit_order[] = "exit\0"; 
char const order[] = ">/tmp/test.txt\0"; 
// do something 
write(ios[1], order, strlen(order)); 
// bash should stop then.. 
write(ios[1], exit_order, strlen(exit_order));   
return 0; 
}

person TecDroiD    schedule 08.11.2012    source источник
comment
я просто хотел увидеть результат. › /tmp/test.txt должен был создать файл в /tmp, но этого не произошло.   -  person TecDroiD    schedule 08.11.2012


Ответы (1)


Я вижу два возможных источника неприятностей:

1) часть записи канала перенаправляется на дочерний стандартный вывод, поэтому выходные данные нового процесса отправляются обратно на вход. Я предлагаю дублировать только прочитанную часть канала на дочерней стороне. Если вы хотите перехватить вывод дочернего элемента, вам нужен другой канал (т. е. новый канал или просто позволить и родительскому, и дочернему разделять один и тот же стандартный вывод).

2) строки, которые вы отправляете, содержат линейно-ориентированные команды. Возможно, дочерний процесс ожидает символы новой строки в конце строк. Это очень распространенный источник проблем. Я предлагаю проверить, как ребенок читает свой ввод. Может помочь "\n" в конце строк (кстати, нет необходимости явно добавлять "\0" в конце строк C, так как компилятор сделает это за вас. В любом случае, strlen не будет считать "\0").

person Giuseppe Guerrini    schedule 08.11.2012
comment
как понимать новую трубу? - person TecDroiD; 09.11.2012
comment
Если вы хотите захватить вывод дочернего элемента, вы должны перенаправить его куда-то так же, как вы перенаправляете ввод. Часто используемое решение — создание второго канала, часть записи которого связана с выводом дочернего элемента. Конечно, родитель должен читать из второго канала, чтобы получить вывод потомка. Но это зависит от вашего конкретного приложения. Самый простой способ — вообще ничего не делать, поэтому потомок наследует вывод родителя. В любом случае, в вашем коде перенаправление дочернего вывода на записывающую часть канала очень странно, поскольку процесс в конечном итоге отправляет свой вывод самому себе. - person Giuseppe Guerrini; 09.11.2012