Перенаправление вывода exec в буфер или файл

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

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

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

 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) { } } 

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

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

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

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

Вариант 2: Труба

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

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

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

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

Давайте будем гением компьютера.