Руководство программиста для Linux

    778b1c86   

Каналы - легкий путь!


Если все изложенные выше изыскания кажутся слишком размытым способом создания и использования каналов, то вот альтернатива этому. LIBRARY FUNCTION: popen(); PROTOTYPE: FILE *popen ( char *command, char *type ); RETURNS: новый файловый поток в случае успеха NULL при неудачном fork() или pipe() NOTES: создает канал, и выполняет fork/exec, используя command

Эта стандартная библиотечная функция создает полудуплексный канал посредством вызывания pipe() внутренне. Затем она порождает дочерний процесс, запускает Bourne shell и исполняет аргумент command внутри shell-а. Управление потоком данных определяется вторым аргументом, type. Он может быть "r" или "w" - для чтения или записи, но не может быть и то, и другое! Под Linux-ом канал будет открыт в виде, определенном первой литерой аргумента "type". Поэтому, если вы попытаетесь ввести "rw", канал будет открыт только в виде "read".

Каналы, созданные popen(), должны быть закрыты pclose(). К этому моменту вы, вероятно, уже использовали [реализовали] popen/pclose share, удивительно похожий на стандартный файловый поток I/O функций fopen() и fclose().LIBRARY FUNCTION: pclose(); PROTOTYPE: int pclose( FILE *stream ) RETURNS: выход из статуса системного вызова wait4() -1, если "stream" некорректен или облом с wait4() NOTES: ожидает окончания связанного каналом процесса, затем закрывает поток.

Функция pclose() выполняет wait4() над процессом, порожденным popen()-ом. Когда она возвращается, то уничтожает канал и файловый поток. Повторим еще раз, что этот эффект аналогичен эффекту, вызываемому функцией fclose() для нормального, основанного на потоке файлового ввода/вывода.

Рассмотрим пример, который открывает канал для команды сортировки и начинает сортировать массив строк: /**************************************************************************** Excerpt from "Linux Programmer's Guide - Chapter 6" (C)opyright 1994-1995, Scott Burkett **************************************************************************** MODULE: popen1.c ****************************************************************************/ #include #define MAXSTRS 5 int main(void) { int cntr; FILE *pipe_fp; char *strings[MAXSTRS] = {"echo", "bravo", "alpha", "charlie", "delta"}; /* Создаем односторонний канал вызовом popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { perror("popen"); exit(1); } /* Цикл */ for(cntr=0; cntr /tmp/foo", "w") popen("sort | uniq | more", "w");




В качестве другого примера popen()-а, рассмотрим маленькую программу, открывающую два канала (один - для команды ls, другой - для сортировки): **************************************************************************** Excerpt from "Linux Programmer's Guide - Chapter 6" (C)opyright 1994-1995, Scott Burkett **************************************************************************** MODULE: popen2.c ****************************************************************************/ #include int main(void) { FILE *pipein_fp, *pipeout_fp; char readbuf[80]; /* Создаем односторонний канал вызовом popen() */ if (( pipein_fp = popen("ls", "r")) == NULL) { perror("popen"); exit(1); } /* Создаем односторонний канал вызовом popen() */ if (( pipeout_fp = popen("sort", "w")) == NULL) { perror("popen"); exit(1); } /* Цикл */ while(fgets(readbuf, 80, pipein_fp)) fputs(readbuf, pipeout_fp); /* Закрываем каналы */ pclose(pipein_fp); pclose(pipeout_fp); return(0); }

В качестве последней демонстрации popen(), давайте создадим программу, характерную для открытия канала между отданной командой и именем файла: /**************************************************************************** Excerpt from "Linux Programmer's Guide - Chapter 6" (C)opyright 1994-1995, Scott Burkett **************************************************************************** MODULE: popen3.c ****************************************************************************/ #include int main(int argc, char *argv[]) { FILE *pipe_fp, *infile; char readbuf[80]; if( argc != 3 ) { fpintf(stderr, "USAGE": popen3 [command] [filename]\n); exit(1); } /* Открываем вводимый файл */ if (( infile = popen(argv[2], "rt")) == NULL) { perror("fopen"); exit(1); } /* Создаем односторонний канал вызовом popen() */ if (( pipe_fp = popen(argv[1], "w")) == NULL) { perror("popen"); exit(1); } /* Цикл */ do { fgets(readbuf, 80, infile); if(feof(infile)) break; fputs(readbuf, pipe_fp); } while(!feof(infile)); fclose(infile); pclose(pipe_fp); return(0); }

Попробуйте выполнить эту программу с последующими заклинаниями: popen3 sort popen3.c popen3 cat popen3.c popen3 more popen3.c popen3 cat popen3.c | grep main


Содержание раздела