□ стандартный вывод cmd2подсоединен к экрану терминала.
На самом деле командная оболочка заново соединила потоки стандартных ввода и вывода так, что потоки данных проходят с клавиатурного ввода через две команды и выводятся на экран. На рис. 13.1 приведено визуальное представление этого процесса.
Рис. 13.1
В этой главе вы увидите, как достичь этого эффекта в программе и как можно использовать каналы для связи многих процессов, что позволит создать простую клиент-серверную систему.
Возможно, простейший способ передачи данных между программами — применение функций popenи pclose. У них следующие прототипы:
#include
FILE *popen(const char *command, const char *open_mode);
int pclose(FILE *stream_to_close);
Функция popen позволяет программе запустить другую программу как новый процесс и либо передать ей данные, либо получить их из нее. Строка command— это имя программы для выполнения вместе с любыми параметрами, параметр open_modeдолжен быть "r"или "w".
Если open_mode— "r", вывод вызванной программы становится доступен вызывающей программе и может быть считан из возвращаемого функцией popenфайлового потока FILE*с помощью обычных функций библиотеки stdio, предназначенных для чтения (например, fread). Но если open_mode— "w", программа может отправить данные вызванной команде с помощью вызова функции fwrite. Далее вызванная программа сможет читать данные из своего стандартного ввода. Обычно вызванная программа не знает, что она считывает данные из другого процесса; она просто читает свой поток стандартного ввода и воздействует на него.
Вызов функции popenдолжен задавать "r"или "w"; никакого другого значения стандартной реализацией popen не поддерживается. Это означает, что вы не можете вызвать другую программу и одновременно читать из нее и писать в нее. В случае сбоя popenвозвращает пустой указатель. Если вы хотите создать двунаправленную связь с помощью каналов, стандартное решение — применить два канала: по одному для потока данных каждого направления.
Когда процесс, стартовавший с помощью popen, закончится, вы можете закрыть файловый поток, связанный с ним, с помощью функции pclose. Вызов pcloseвернет управление, только когда процесс, запущенный с помощью popen, завершится. Если он все еще выполняется во время вызова pclose, вызов pcloseбудет ждать окончания процесса.
Функция pcloseобычно возвращает код завершения процесса, чей файловый поток она закрывает. Если вызывающий процесс уже выполнил оператор waitперед вызовом pclose, статус завершения будет потерян, поскольку вызванный процесс закончен, и функция pcloseвернет -1 с переменной errno, получившей значение ECHILD.
Выполните упражнение 13.1.
Упражнение 13.1. Чтение вывода внешней программы
Давайте опробуем простой пример popen1.c с функциями popenи pclose. Вы будете применять в программе popenдля доступа к информации из uname. uname— это команда, выводящая системную информацию, включая тип компьютера, имя ОС, версию и выпуск, а также сетевое имя машины.
Запустив программу, вы откроете канал к uname; сделаете его читаемым и зададите read_fp, как указатель на вывод. В конце канал, на который указывает read_fp, закрывается.
#include
#include
#include
#include
int main() {
FILE *read_fp;
char buffer[BUFSIZ +1];
int chars_read;
memset(buffer, '\0', sizeof(buffer));
read_fp = popen("uname -a", "r");
if (read_fp ! = NULL) {
chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
if (chars_read > 0) {
printf("Output was:-\n%s\n", buffer);
}
pclose(read_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
Когда вы выполните программу, то должны получить вывод, похожий на следующий (полученный на одной из машин авторов):
Читать дальше