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

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

//bench/lat_door.c

1  #include "unpipc.h"

2  void

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

4   door_desc_t *dp, size_t n_descriptors)

5  {

6   char c;

7   Door_return(&c, sizeof(char), NULL, 0);

8  }

9  int

10 main(int argc, char **argv)

11 {

12  int i, nloop, doorfd, contpipe[2];

13  char c;

14  pid_t childpid;

15  door_arg_t arg;

16  if (argc != 3)

17   err_quit("usage: lat_door <pathname> <#loops>");

18  nloop = atoi(argv[2]);

19  unlink(argv[1]);

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

21  Pipe(contpipe);

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

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

24   Fattach(doorfd, argv[1]);

25   Write(contpipe[1], &c, 1);

26   for(;;) /* дочерний процесс = сервер */

27    pause();

28   exit(0);

29  }

30  arg.data_ptr = &c; /* родительский процесс = клиент */

31  arg.data_size = sizeof(char);

32  arg.desc_ptr = NULL;

33  arg.desc_num = 0;

34  arg.rbuf = &c;

35  arg.rsize = sizeof(char);

36  if (Read(contpipe[0], &c, 1) != 1) /* ждем создания */

37   err_quit("pipe read error");

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

39  Door_call(doorfd, &arg); /* запуск */

40  Start_time();

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

42   Door_call(doorfd, &arg);

43  printf("latency: %.3f usec\n", Stop_time() / nloop);

44  Kill(childpid, SIGTERM);

45  unlink(argv[1]);

46  exit(0);

47 }

Программа измерения времени задержки Sun RPC

Для измерения времени задержки Sun RPC мы напишем две программы: клиент и сервер, аналогично измерению полосы пропускания. Мы используем старый файл спецификации RPC, но на этот раз клиент вызывает нулевую процедуру сервера. Вспомните упражнение 16.11: эта процедура не принимает никаких аргументов и ничего не возвращает. Это именно то, что нам нужно, чтобы определить задержку. В листинге А.18 приведен текст клиента. Как и в решении упражнения 16.11, нам нужно воспользоваться clnt_call для вызова нулевой процедуры; в заглушке клиента отсутствует необходимая заглушка для этой процедуры.

Листинг А.18. Клиент Sun RPC для измерения задержки

//bench/lat_sunrpc_client.с

1  #include "unpipc.h"

2  #include "lat_sunrpc.h"

3  int

4  main(int argc, char **argv)

5  {

6   int i, nloop;

7   CLIENT *cl;

8   struct timeval tv;

9   if (argc != 4)

10   err_quit("usage: lat_sunrpc_client <hostname> <#loops> <protocol>");

11  nloop = atoi(argv[2]);

12  cl = Clnt_create(argv[1], BW_SUNRPC_PROG, BW_SUNRPC_VERS, argv[3]);

13  tv.tv_sec = 10;

14  tv.tv_usec = 0;

15  Start_time();

16  for (i = 0; i < nloop; i++) {

17   if (clnt_call(cl, NULLPROC, xdr_void, NULL,

18    xdr_void, NULL, tv) != RPC_SUCCESS)

19    err_quit("%s", clnt_sperror(cl, argv[1]));

20  }

21  printf("latency: %.3f usec\n", Stop_time() / nloop);

22  exit(0);

23 }

Мы компилируем сервер с функцией, приведенной в листинге А.13, но она все равно не вызывается. Поскольку мы используем rpcgen для построения клиента и сервера, нам нужно определить хотя бы одну процедуру сервера, но мы не обязаны ее вызывать. Причина, по которой мы используем rpcgen, заключается в том, что она автоматически создает функцию main сервера с нулевой процедурой, которая нам нужна.