Книга: Разработка приложений в среде Linux. Второе издание
10.5.2. Чтение и запись из процесса
10.5.2. Чтение и запись из процесса
Хотя system()
отображает результат работы команды на устройство стандартного вывода и позволяет дочерним программам читать стандартный ввод, это не всегда идеально. Часто процесс желает читать вывод другого процесса либо отправлять текст на стандартный ввод. popen()
облегчает процессам решение этой задачи[29].
FILE * popen(const char *cmd, const char *mode);
выполняется через оболочку, как и в
cmdsystem()
. Параметр 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()
запускает команды через системную оболочку и должна использоваться с большой осторожностью, если вызывается из программы со специальными полномочиями.
- Чтение закрытых каналов
- Чтение файла
- Запись в файл
- 11.2.5. Частичное чтение и запись
- 7.2.5. Дескрипторы файлов процесса
- Сущность процесса миграции
- V Совершенствование процесса
- Использование сервера Yaffil внутри процесса
- 4. Стадии бизнес-процесса взаимодействия с клиентами
- 4.4.3. Чтение и запись
- 2.2.2.2 Состояния процесса
- 1.2 Процесс, контекст процесса и потоки