2016-04-09 5 views
0

Я пытаюсь получить простой переадресацию ввода/вывода, используя dup2. Я следил точно за кодом, который говорят другие люди, но до сих пор нет успеха.Перенаправление stdout, не понимаю поведения

int out = open("stdoutput", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 
printf("STANDARD OUT\n"); 
dup2(out, 1); 
printf("SEND TO FILE\n"); 
dup2(1, out); 
close(out); 
printf("BACK TO STANDARD OUT\n"); 

Печатается STANDARD OUT к терминалу и SEND TO FILE BACK TO STANDARD OUT к файлу. Почему он не возвращается?

Я также хочу, чтобы файл stdout fork/exec выводил файл.

int out2 = open("execout", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 
printf("STANDARD OUT\n"); 
dup2(out2, 1); 
if(fork() == 0) 
{ 
    execvp("time", NULL); 
    perror(NULL); 
} 

dup2(out2, 1); 
close(out2); 
printf("BACK TO STANDARD OUT\n"); 

Это выводит на терминал:

STANDARD OUT TERM_PROGRAM = Apple_Terminal: Нет такого файла или каталога 0,00 реальный 0,00 пользователя 0,00 SYS

и в файл execout, он печатает: BACK TO STANDARD OUT

Возможно, возникла некоторая дополнительная проблема с вызовом exec вовремя (не найти его, а затем распечатать его в любом случае?), Но моя основная проблема с перенаправлением ввода-вывода не работает правильно.

Заранее за вашу помощь.


Обновление: похоже, проблема связана с тем, что exec не отправляет результат в файл. Код:

int output_file = open("gcc_output", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 

if(fork() == 0) 
{ 
    dup2(output_file, 1); 
    close(output_file); 
    char *args[] = {"gcc", path, NULL}; 
    printf("THIS GOES TO FILE"); 
    execvp(args[0], args); // gcc output, errors etc. go to terminal 
    perror("exec"); 
    exit(2); 
} 

Выполняет ли exec, что он потерял свои файловые дескрипторы или что-то еще?

+0

Он не переключается обратно, потому что 'out' и' 1' совпадают после первого вызова 'dup2', поэтому второй вызов' dup2' ничего не делает. – user3386109

+0

И было бы полезно проверить результаты ваших вызовов 'dup2', чтобы подтвердить это. – WhozCraig

+0

при вызове системных функций: 'dup2()' и 'open()', всегда проверяйте возвращаемое значение, чтобы убедиться, что операция прошла успешно. – user3629249

ответ

0

dup2(from, to) копирует дескриптор файла from в дескриптор файла to; если to был открыт, он незамкнуто закрыт перед перезаписью.

В первом примере вы открываете файл stdoutput для записи; ему предоставляется наименьшее возможное число дескрипторов (возможно, 3); то ваш dup2(out2, 1) копирует этот дескриптор над стандартным дескриптором вывода 1; исходный стандартный выход молча закрыт. Есть в настоящее время 4 открытые дескрипторы:

  • 0 оригинальный стандартный ввод
  • 1 открыт для записи в файл stdoutput
  • 2 оригинальный стандартный вывод
  • 3 открыт для записи в файл stdoutput

Наконец, вы пытаетесь «восстановить» исходный стандартный вывод, скопировав дескриптор файла 1 поверх дескриптора файла 3.

Вместо этого, вы должны уже сохранили оригинальный стандартный вывод в другой файл дескриптора по dup:

int out = open("stdoutput", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 
printf("STANDARD OUT\n"); 
int saved_stdout = dup(1); // create a copy of the stdout file descriptor 
dup2(out, 1); 
close(out);    // close the extra descriptor 
printf("SEND TO FILE\n"); 
dup2(saved_stdout, 1);  // copy the saved stdout file descriptor to 1 
close(saved_stdout);  // close the copy of stdout 
printf("BACK TO STANDARD OUT\n"); 

Ваш execvp вызов сломаны тоже; должен быть дополнительный аргумент, который является именем команды; также time не печатает текущую дату, но является командой, которая ожидает другую команду в качестве аргумента - возможно, вы хотели выполнить команду date? Кроме того, вы должны сделать dup2только в дочернем процессе после вилки! Попробуйте выполнить следующие действия:

int out2 = open("execout", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 
printf("STANDARD OUT\n"); 
if (fork() == 0) { 
    dup2(out2, 1); 
    close(out2); 
    execvp("date", "date", (char *)NULL); 
    perror("exec"); 
    exit(2); 
} 
close(out2); 
printf("STILL POINTING TO STANDARD OUT\n"); 
+0

Спасибо за четкое объяснение. По-прежнему возникают проблемы с exec (обновлен мой вопрос). –

Смежные вопросы