Читать «UNIX: взаимодействие процессов» онлайн - страница 311

Уильям Ричард Стивенс

20  Touch(buf, xfersize);

21  unlink(argv[1]);

22  Close(Open(argv[1], O_CREAT | O_EXCL | O_RDWR, FILE_MODE));

23  Pipe(contpipe); /* предполагается наличие двустороннего канала SVR4 */

24  if ((childpid = Fork()) == 0) {

25   /* дочерний процесс = клиент */

26   if ((n = Read(contpipe[0], &c, 1)) != 1)

27    err_quit("child: pipe read returned %d", n);

28   doorfd = Open(argv[1], O_RDWR);

29   writer(doorfd);

30   exit(0);

31  }

32  /* родительский процесс = сервер */

33  doorfd = Door_create(server, NULL, 0);

34  Fattach(doorfd, argv[1]);

35  Write(contpipe[1], &c, 1); /* уведомление о готовности двери */

36  Start_time();

37  for (i = 0; i < nloop; i++)

38   reader(doorfd, totalnbytes);

39  printf("bandwidth: %.3f MB/sec\n",

40  totalnbytes / Stop_time() * nloop);

41  kill(childpid, SIGTERM);

42  unlink(argv[1]);

43  exit(0);

44 }

Листинг A.10. Функции writer, server, reader для интерфейса дверей

//bench/bw_door.c

45 void

46 writer(int doorfd)

47 {

48  int ntowrite;

49  door_arg_t arg;

50  arg.desc_ptr = NULL; /* дескрипторы не передаются */

51  arg.desc_num = 0;

52  arg.rbuf = NULL; /* значения не возвращаются */

53  arg.rsize = 0;

54  for(;;) {

55   Read(contpipe[0], &ntowrite, sizeof(ntowrite));

56   while (ntowrite > 0) {

57    arg.data_ptr = buf;

58    arg.data_size = xfersize;

59    Door_call(doorfd, &arg);

60    ntowrite –= xfersize;

61   }

62  }

63 }

64 static int ntoread, nread;

65 void

66 server(void *cookie, char *argp, size_t arg_size,

67  door_desc_t *dp, size_t n_descriptors)

68 {

69  char c;

70  nread += arg_size;

71  if (nread >= ntoread)

72   Write(contpipe[0], &c, 1); /* запись закончена */

73  Door_return(NULL, 0, NULL, 0);

74 }

75 void

76 reader(int doorfd, int nbytes)

77 {

78  char c;

79  ssize_t n;

80  ntoread = nbytes; /* глобальные переменные процедуры сервера */

81  nread = 0;

82  Write(contpipe[1], &nbytes, sizeof(nbytes));

83  if ((n = Read(contpipe[1], &c, 1)) != 1)

84   err_quit("reader: pipe read returned %d", n);

85 }

Программа определения полосы пропускания Sun RPC

Поскольку вызовы процедур в Sun RPC являются синхронными, для них действует то же ограничение, что и для дверей (см. выше). В данном случае проще создать две программы (клиент и сервер), поскольку они создаются автоматически программой rpcgen. В листинге А.11 приведен файл спецификации RPC. Мы объявляем единственную процедуру, принимающую скрытые данные переменной длины в качестве входного аргумента и ничего не возвращающую.

В листинге А.12 приведен текст программы-клиента, а в листинге А.13 — процедура сервера. Мы указываем протокол в качестве аргумента командной строки при вызове клиента, что позволяет нам измерить скорость работы обоих протоколов.

Листинг А.11. Спецификация RPC для измерения полосы пропускания RPC

//bench/bw_sunrpc.х

1 %#define DEBUG /* сервер выполняется в приоритетном режиме */

2 struct data_in {

3  opaque data<>; /* скрытые данные переменной длины */

4 };

5 program BW_SUNRPC_PROG {

6  version BW_SUNRPC_VERS {

7   void BW_SUNRPC(data_in) = 1;