Книга: Разработка приложений в среде Linux. Второе издание

10.5.2. Чтение и запись из процесса

10.5.2. Чтение и запись из процесса

Хотя system() отображает результат работы команды на устройство стандартного вывода и позволяет дочерним программам читать стандартный ввод, это не всегда идеально. Часто процесс желает читать вывод другого процесса либо отправлять текст на стандартный ввод. popen() облегчает процессам решение этой задачи[29].

FILE * popen(const char *cmd, const char *mode);
cmd
выполняется через оболочку, как и в system(). Параметр mode должен быть "r", если родительский процесс желает читать командный вывод, и "w" — для записи в стандартный ввод дочернего процесса. Следует отметить, что с помощью popen() делать одновременно чтение и запись нельзя.

Два процесса, которые читают и пишут друг в друга, достаточно сложны[30] и выходят за рамки возможностей popen()[31].

popen() возвращает FILE* (как это определено в стандартной библиотеке ввода-вывода ANSI/ISO), который может быть прочитан и записан подобно любому другому потоку stdio[32], либо NULL, если операция не удается. Когда завершается родительский процесс, он может воспользоваться pclose() для закрытия потока и прерывания дочернего процесса, если он все еще выполняется. Подобно system(), pclose() возвращает состояние дочернего процесса из wait4().

int pclose(FILE *stream);

Ниже приведен пример простой программы-калькулятора, которая использует программу bc для выполнения всей реальной работы. Важно сбрасывать поток, полученный от popen(), после записи в него, чтобы предотвратить буферизацию stdio от задержки вывода (подробности о буферизации стандартных функций библиотеки stdio можно найти в [15]).

 1: /*calc.c*/
 2:
 3: /* Это очень простой калькулятор, который использует внешнюю команду bc
 4:    для выполнения всей работы. Открывает канал к bc, читает команду,
 5:    передает ее bc и завершается. */
 6: #include <stdio.h>
 7: #include <sys/wait.h>
 8: #include <unistd.h>
 9:
10: int main(void) {
11:  char buf[1024];
12:  FILE *bc;
13:  int result;
14:
15:  /* открыть канал на bc и выйти в случае неудачи */
16:  bc = popen("bc", "w");
17:  if (!bc) {
18:   perror("popen");
19:   return 1;
20:  }
21:
22:  /* пригласить ввести выражение, и прочитать его */
23:  printf("expr:"); fflush(stdout);
24:  fgets(buf, sizeof(buf), stdin);
25:
26:  /* послать выражение bc для вычисления */
27:  fprintf(bc, "%sn", buf);
28:  fflush(bc);
29:
30:  /* закрыть канал на bc и ожидать выхода из нее */
31:  result = pclose(bc);
32:
33:  if (!WIFEXITED(result))
34:   printf("(аварийный выход)n");
35:
36:  return 0;
37: }

Подобно system(), popen() запускает команды через системную оболочку и должна использоваться с большой осторожностью, если вызывается из программы со специальными полномочиями.

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


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