Пример 24



/* Пример коммуникации процессов при помощи программных каналов

 * (трубы, pipes).

 *      Данная программа превращается в две программы,

 *      соединенные трубами в таком порядке:

 *

 *         stdout                  stdin

 *        /------------ PIP1 -----------> cmd2

 *      cmd1 <----------PIP2---------------/

 *         stdin                   stdout

 */

/* файл LOOP_strt.c */

#include <stdio.h>

#define eq(s1,s2) ( strcmp(s1,s2) == 0 ) /* истина, если строки равны */

#define SEP         "---"                /* разделитель команд при наборе */

main( c, v ) char **v;

{

	char **p, **q;

	int pid;

	int PIP1[2];    /* труба cmd1-->cmd2 */

	int PIP2[2];    /* труба cmd2-->cmd1 */

	if( c==1 ){

		printf( "Call: strt cmd1... %s cmd2...\n", SEP );

		exit(1);

	}

			/* разбор аргументов */

	v++;

	/* в p - аргументы первой команды */

	p = v;

	while( *v && !eq( *v, SEP ))

		v++;

	*v = NULL;

	v++;

	/* в q - аргументы второй команды */

	q = v;

	pipe( PIP1 );   /* создаем две трубы */

	pipe( PIP2 );   /* PIP[0] - открыт на чтение, PIP[1] - на запись */

	if( pid = fork()){      /* развилка: порождаем процесс */

	/* ПОРОЖДЕННЫЙ ПРОЦЕСС */

		fprintf( stderr, "сын=%s pid=%d\n", p[0], getpid());

		/* перенаправляем stdout нового процесса в PIP1 */

		dup2( PIP1[1], 1 );

		close( PIP1[1] );

		/* канал чтения мы не будем использовать */

		   close( PIP1[0] );

		/* перенаправляем stdin из PIP2 */

		dup2( PIP2[0], 0 );

		close( PIP2[0] );

		/* канал записи мы не будем использовать */

		   close( PIP2[1] );

		/* начинаем выполнять программу, содержащуюся в

		 * файле p[0] с аргументами p (т.е. cmd1)

		 */

		execvp( p[0], p );

		/* возврата из сисвызова exec не бывает */

	}else{

	/* ПРОЦЕСС-РОДИТЕЛЬ */

		fprintf( stderr, "отец=%s pid=%d\n", q[0], getpid());

		/* перенаправляем stdout в PIP2 */

		dup2( PIP2[1], 1 );

		close( PIP2[1] ); close( PIP2[0] );

		/* перенаправляем stdin из PIP1 */

		dup2( PIP1[0], 0 );

		close( PIP1[0] ); close( PIP1[1] );

		/* запускаем cmd2 */

		execvp( q[0], q );

	}

}

/* Ниже приводятся тексты двух программ, которые можно запустить

 * как тест. Сервер компилируется в программу cmd2,

 * клиент - в программу cmd1. Если запускающая программа

 * скомпилирована в strt, то наберите команду

 *              strt cmd1 --- cmd2

 *  либо        strt cmd2 --- cmd1

 */

/* файл LOOP_p.c --------------------------------------------

 * Процесс-клиент (cmd1)

 */

#include <stdio.h>

int trace = 1;  /* вести трассировку своих действий */

main(c , v) char **v;

{

	FILE *fp;       int pid;

	char buf[128];

	fprintf( stderr, "P: process pid=%d\n", getpid());

	fp = fopen( "LOOP_p.c", "r" );

	/* открываем файл с текстом этой команды */

	/* читаем его построчно */

	while( fgets( buf, sizeof buf, fp ) != NULL ){

		if( trace ) fprintf( stderr, "P посылает: %s", buf );

		/* посылаем его в стандартный вывод: трубу PIP1 */

		printf( "%s", buf );

		fflush( stdout );

		/* ожидать ответа из трубы PIP2 */

		fgets( buf, sizeof buf, stdin );

		if( trace ) fprintf( stderr, "P получил: %s", buf );

	}

	fclose( stdout );

	/* отключиться от трубы PIP1. Если этого не сделать, сервер

	 * не прочитает из нее EOF */

	while((pid = wait(NULL)) > 0 )

		fprintf( stderr, "P: %d умер\n", pid );

}

/* файл LOOP_q.c -----------------------------------------------

 * процесс-сервер (cmd2)

 */

#include <stdio.h>

int trace = 1;

main(c , v) char **v;

{

	char buf[128];          int pid;

	fprintf( stderr, "Q: process pid=%d\n", getpid());

	/* читать поступающие из трубы PIP1 строки */

	while( fgets( buf, sizeof(buf), stdin ) != NULL ){

		/* напечатать полученное сообщение */

		if( trace ) fprintf( stderr, "Q прочел: %s", buf );

		if( trace ) fprintf( stderr, "Q отвечает: OK=%s", buf );

		/* ответить в трубу PIP2 */

		printf( "OK=%s", buf ); fflush( stdout );

	}

	fclose( stdout );       /* отключиться от трубы PIP2 */

	while((pid = wait(NULL)) > 0 )

		fprintf( stderr, "Q: %d умер\n", pid );

}

[Назад][Содержание][Вперед]

Используются технологии uCoz