Перенаправление должностного лица произвело к буферу или файлу

Я пишу программу C где я fork(), exec(), и wait(). Я хотел бы взять вывод программы I exec'ed для записи этого в файл или буфер.

Например, если я должностное лицо ls Я хочу записать file1 file2 etc буферизовать/регистрировать. Я не думаю, что существует способ считать stdout, который означает, что я должен использовать канал? Существует ли общая процедура здесь, что я не смог найти?

40
задан alk 17 November 2015 в 14:16
поделиться

4 ответа

Для отправки вывода в другой файл (я опускаю проверку ошибок, чтобы сосредоточиться на важных деталях):

if (fork() == 0)
{
    // child
    int fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

    dup2(fd, 1);   // make stdout go to file
    dup2(fd, 2);   // make stderr go to file - you may choose to not do this
                   // or perhaps send stderr to another file

    close(fd);     // fd no longer needed - the dup'ed handles are sufficient

    exec(...);
}

Для отправки вывода в трубу, чтобы вы могли прочитать вывод в буфер:

int pipefd[2];
pipe(pipefd);

if (fork() == 0)
{
    close(pipefd[0]);    // close reading end in the child

    dup2(pipefd[1], 1);  // send stdout to the pipe
    dup2(pipefd[1], 2);  // send stderr to the pipe

    close(pipefd[1]);    // this descriptor is no longer needed

    exec(...);
}
else
{
    // parent

    char buffer[1024];

    close(pipefd[1]);  // close the write end of the pipe in the parent

    while (read(pipefd[0], buffer, sizeof(buffer)) != 0)
    {
    }
}
86
ответ дан 27 November 2019 в 01:17
поделиться

Вам нужно точно решить, что вы хотите делать, и, желательно, объяснить это немного более четко.

Вариант 1: Файл

Если вы знаете, в какой файл вы хотите переместить вывод выполненной команды, тогда:

  1. Убедитесь, что родительский и дочерний элементы согласовали имя (родитель определяет имя перед разветвлением).
  2. Родительские вилки - у вас есть два процесса.
  3. Дочерний элемент реорганизует вещи так, что дескриптор файла 1 (стандартный вывод) переходит в файл.
  4. Обычно стандартную ошибку можно оставить в покое; вы можете перенаправить стандартный ввод из / dev / null.
  5. Потомок выполняет соответствующую команду; указанная команда запускается, и любой стандартный вывод поступает в файл (это базовое перенаправление ввода-вывода оболочки).
  6. Выполненный процесс завершается.
  7. Между тем, родительский процесс может использовать одну из двух основных стратегий:
    • Откройте файл для чтения и продолжайте чтение, пока он не достигнет EOF. Затем ему необходимо дважды проверить, умер ли ребенок (чтобы больше не было данных для чтения), или ждать, пока ребенок не введет дополнительные данные.
    • Подождите, пока ребенок умрет, а затем откройте файл для чтения.
    • Преимущество первого состоит в том, что родитель может выполнять часть своей работы, в то время как дочерний элемент также работает; Преимущество второго в том, что вам не нужно возиться с системой ввода-вывода (многократно читая после EOF).

Вариант 2: Канал

Если вы хотите, чтобы родитель считывал вывод дочернего элемента, организуйте, чтобы дочерний элемент передавал свой вывод обратно родителю.

  1. Используйте popen (), чтобы сделать это простым способом. Он запустит процесс и отправит вывод вашему родительскому процессу.Обратите внимание, что родительский элемент должен быть активен, пока дочерний элемент генерирует выходные данные, поскольку каналы имеют небольшой размер буфера (часто 4-5 КБ), и если дочерний элемент генерирует больше данных, чем это, пока родитель не читает, дочерний элемент будет блокироваться до тех пор, пока родитель читает. Если родитель ждет смерти ребенка, вы зашли в тупик.
  2. Используйте pipe () и т. Д., Чтобы сделать это сложным способом. Родитель вызывает pipe (), а затем выполняет разветвление. Дочерний элемент сортирует каналы так, чтобы конец канала для записи был его стандартным выходом, и гарантирует, что все другие файловые дескрипторы, относящиеся к каналу, закрыты. Для этого вполне можно использовать системный вызов dup2 (). Затем он выполняет требуемый процесс, который отправляет свой стандартный вывод по конвейеру.
  3. Между тем, родительский объект также закрывает нежелательные концы канала и затем начинает чтение. Когда он получает EOF на конвейере, он знает, что дочерний элемент закончил и закрыл канал; он также может закрыть конец трубы.
15
ответ дан 27 November 2019 в 01:17
поделиться

Поскольку похоже, что вы собираетесь использовать это в среде linux / cygwin, вы хотите использовать popen . Это похоже на открытие файла, только вы получите исполняемые программы stdout , так что вы можете использовать свои обычные fscanf , fread и т. Д.

{{ 1}}
2
ответ дан 27 November 2019 в 01:17
поделиться

После форка используйте dup2(2) для дублирования FD файла в FD stdout, затем выполните.

1
ответ дан 27 November 2019 в 01:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: