$ ./popen1
Output was:-
Linux suse103 2.6.20.2-2-default #1 SMP Fri Mar 9 21:54:10 UTC 2001 i686 i686 i386 GNU/Linux
Как это работает
Программа применяет функцию popenдля вызова команды unameс параметром -а. Затем она использует возвращенный файловый поток для чтения данных, до BUFSIZсимволов (как задано в директиве #defineиз файла stdio.h), и затем выводит их на экран. Поскольку вы перехватываете вывод команды uname внутри программы, его можно обрабатывать.
Теперь, когда вы рассмотрели пример захвата вывода из внешней программы, давайте познакомимся с отправкой вывода во внешнюю программу. В упражнении 13.2 показана программа popen2.c, передающая по каналу данные другой программе. В этом примере будет использована команда od (от англ. octal dump — восьмеричный дамп).
Упражнение 13.2. Пересылка вывода в другую программу
Взглянув на следующий программный код, вы увидите, что он очень похож на предыдущий пример, за исключением того, что вы пишете данные в канал вместо чтения данных из него. Далее приведена программа popen2.c.
#include
#include
#include
#include
int main() {
FILE *write_fp;
char buffer[BUFSIZ + 1];
sprintf(buffer, "Once upon a time, there was...\n");
write_fp = popen("od -c", "w");
if (write_fp != NULL) {
fwrite(buffer, sizeof(char), strlen(buffer), write_fp);
pclose(write_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
После выполнения этой программы вы должны получить следующий вывод:
$ ./popen2
0000000 O n c e u p o n a t i m e
0000020 , t h e r e w a s . . . \n
0000037
Как это работает
Программа применяет popenс параметром "w" для запуска команды od -стаким образом, что может отправить данные этой команде. Затем она отправляет строку, которую команда od -сполучает и обрабатывает; далее команда od -свыводит результат обработки в своем стандартном выводе.
Такой же вывод можно получить из командной строки с помощью следующей команды:
$ echo "Once upon a time, there was..." | od -c
Передача данных большого объема
Механизм, применявшийся до сих пор, просто отправляет и получает все данные в одном вызове freadили fwrite. Порой вам может понадобиться отправлять данные меньшими порциями или вы не будете знать размера вывода. Для того чтобы не объявлять слишком большой буфер, можно просто применить множественные вызовы freadили fwriteи обрабатывать данные порциями.
В упражнении 13.3 приведена программа popen3.c, читающая все данные из канала.
Упражнение 13.3. Чтение из канала данных большого объема
В этой программе вы читаете данные из вызванного процесса ps ах. У вас нет возможности узнать заранее, какой величины будет вывод, поэтому вы должны разрешить множественные операции чтения из канала.
#include
#include
#include
#include
int main() {
FILE * read_fp;
char buffer[BUFSIZ + 1];
int chars_read;
memset(buffer, '\0' , sizeof(buffer));
read_fp = popen("ps ax", "r");
if(read_fp != NULL) {
chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
while (chars_read > 0) {
buffer[chars_read - 1] = '\0';
printf("Reading %d:-\n %s\n", BUFSIZ, buffer);
chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
}
pclose(read_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
Вывод, отредактированный для краткости, подобен приведенному далее:
$ ./popen3
Reading 1024:-
PID TTY STAT TIME COMMAND
1 ? Ss 0:03 init [5]
2 ? SW 0:00 [kflushd]
3 ? SW 0:00 [kpiod]
4 ? SW 0:00 [kswapd]
5 ? SW< 0:00 [mdrecoveryd]
...
240 tty2 S 0:02 emacs draft1.txt
Reading 1024:-
368 tty1 S 0:00 ./popen 3
369 tty1 R 0:00 ps -ax
370 ...
Как это работает
Программа применяет функцию popenс параметром "r"аналогично программе popen1.c. В этот раз она продолжает чтение из файлового потока до тех пор, пока в нем есть данные. Учтите, что, хотя программе psнужно некоторое время для выполнения, Linux так организует планирование процессов, что обе программы выполняются, когда могут. Если у читающего процесса popen3 нет входных данных, он приостанавливается до появления доступных данных. Если записывающий процесс psформирует вывод, больший по объему, чем может вместить буфер, он приостанавливается до тех пор, пока считывающий процесс не обработает какой-то объем данных.
Читать дальше