Перенаправление вывода дочернего процесса - PullRequest
2 голосов
/ 19 декабря 2011

Существует несколько способов перенаправления вывода дочернего процесса:

  1. с использованием freopen(3)
  2. с использованием dup(3)
  3. с использованием popen(3)
  4. ...

Что нужно выбрать, если все, что нужно, - это запустить дочерний процесс и сохранить его вывод в заданном файле, почти так же, как работает ls > files.txt?

Что обычно используют снаряды?

Ответы [ 2 ]

3 голосов
/ 19 декабря 2011

Вы можете узнать, что использует ваша любимая оболочка, strace(1) используя ее.

В одном терминале:

echo $$

В другом терминале:

strace -o /tmp/shell -f -p [PID from the first shell]

Снова в первом терминале:

ls > files.txt

Во втором терминале, ^C ваша команда strace(1), а затем отредактируйте выходной файл /tmp/shell, чтобы увидеть, какие системные вызовы он сделал для перенаправления.


freopen(3) манипулирует стандартными указателями C IO FILE*. Все это будет отброшено на другой стороне вызова execve(2), поскольку оно поддерживается в пользовательской памяти . Вы можете использовать этот после вызова execve(2), но это было бы неудобно использовать в общем.

popen(3) открывает однонаправленный pipe(7). Это полезно, но крайне ограниченно - вы получаете стандартный дескриптор вывода или стандартный дескриптор ввода. Это потерпит неудачу для чего-то вроде ls | grep foo | sort, где и вход, и выход должны быть перенаправлены. Так что это плохой выбор.

dup2(2) будет управлять файловыми дескрипторами - ресурсом, реализованным в ядре - поэтому он будет сохраняться при execve(2) вызовах и , вы можете установить столько файловых дескрипторов, сколько вам нужно, что неплохо для ls > /tmp/output 2> /tmp/error или для обработки обоих входов и выход: ls | sort | uniq.

Есть еще один механизм: pty(7) обработка. Функции forkpty(3), openpty(3) могут управлять новым псевдо-терминальным устройством, созданным специально для работы с другой программой. Расширенное программирование в среде Unix, 2-е издание содержит очень хороший пример pty в своем исходном коде, хотя, если у вас возникли проблемы с пониманием, почему это было бы полезно, взгляните на script(1) program - создает новый псевдотерминал и использует его для записи всех входных и выходных данных программ и сохраняет их в файле для последующего воспроизведения или документирования. Вы также можете использовать его для сценария действий в интерактивных программах, аналогично expect(1).

2 голосов
/ 19 декабря 2011

Я бы ожидал найти dup2() в основном используемым.

Ни popen(), ни freopen() не предназначены для обработки перенаправлений, таких как 3>&7. До определенного момента можно было использовать dup(), но пример 3>&7 показывает, где dup() начинает скрипеть; вам нужно убедиться, что файловые дескрипторы 4, 5 и 6 открыты (а 7 - нет), прежде чем он обработает то, что dup2() будет делать без суеты.

...