Книга: Основы программирования в Linux

Как реализован вызов popen

Как реализован вызов popen

Вызов popen выполняет программу, которую вы запросили, прежде всего, вызывая командную оболочку sh и передавая ей командную строку как аргумент. У этого процесса две стороны: приятная и не очень.

В ОС Linux (как и во всех UNIX-подобных системах) подстановка всех параметров выполняется командной оболочкой, поэтому вызов оболочки для синтаксического анализа командной строки перед вызовом программы дает возможность командной оболочке выполнить любую подстановку, например, определить реальные файлы, на которые ссылается строка *.с до того, как программа начнет выполняться. Часто это очень полезно и позволяет запускать с помощью popen сложные команды оболочки. Другие функции создания процесса, например execl, гораздо сложнее применять для вызова, поскольку вызывающий процесс должен самостоятельно выполнять подстановки параметров командной оболочки.

Нежелательный эффект применения командной оболочки состоит в том, что для каждого вызова popen вместе с требуемой программой вызывается командная оболочка. Далее каждый вызов popen порождает запуск двух дополнительных процессов, что делает функцию popen немного расточительной с точки зрения расходования системных ресурсов и вызов нужной команды выполняется медленнее, чем было бы в противном случае.

В упражнении 13.4 приведена программа popen4.c, которую можно использовать для демонстрации поведения popen. Вы можете сосчитать количество строк во всех файлах с исходным текстом примеров семейства popen, применив команду cat к файлам и затем пересылая по каналу вывод в команду wc -l, которая считает количество строк. В командной строке эквивалентная команда выглядит следующим образом:

$ cat popen*.c | wc -l

Примечание

На самом деле wc -l popen*.c легче и гораздо эффективнее ввести с клавиатуры, но пример иллюстрирует основные принципы использования каналов.

Упражнение 13.4. Вызов popen запускает командную оболочку

Эта программа применяет в точности предыдущую команду, но с помощью popen, так что она может читать результат.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
 FILE *read_fp;
 char buffer[BUFSIZ +1];
 int chars_read;
 memset(buffer, '', sizeof(buffer));
 read_fp = popen("cat popen*.с | wc -l", "r");
 if (read_fp != NULL) {
  chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
  while (chars_read > 0) {
   buffer[chars_read - 1] = '';
   printf("Reading:-n %sn", buffer);
   chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
  }
  pclose(read_fp);
  exit(EXIT_SUCCESS);
 }
 exit(EXIT_FAILURE);
}

Выполнив эту программу, вы получите следующий вывод:

$ ./popen4
Reading:-
94

Как это работает

Программа показывает, что вызывается командная оболочка для того, чтобы развернуть popen*.с в список всех файлов, начинающихся с popen и заканчивающихся , а также для обработки символа канала (|) и отправки вывода команды cat в команду . Вы вызываете командную оболочку, программы catиwc и задаете перенаправление — все в одном вызове popen. Программа, вызвавшая команду, видит только заключительный вывод.

Оглавление книги


Генерация: 1.405. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз