Категории
Самые читаемые
onlinekniga.com » Компьютеры и Интернет » Программирование » UNIX: взаимодействие процессов - Уильям Стивенс

UNIX: взаимодействие процессов - Уильям Стивенс

Читать онлайн UNIX: взаимодействие процессов - Уильям Стивенс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 113 114 115 116 117 118 119 120 121 ... 128
Перейти на страницу:

Пpoгрaммa измерения задержки для очередей сообщений Posix приведена в листинге А.15.

Листинг А. 15. Программа измерения задержки для очереди сообщений Posix

//bench/lat_pxmsg.с

1  #include "unpipc.h"

2  #define NAME1 "lat_pxmsg1"

3  #define NAME2 "lat_pxmsg2"

4  #define MAXMSG 4 /* место для 4096 байт в очереди */

5  #define MSGSIZE 1024

6  void

7  doit(mqd_t mqsend, mqd_t mqrecv)

8  {

9   char buff[MSGSIZE];

10  Mq_send(mqsend, buff, 1.0);

11  if (Mq_receive(mqrecv, buff, MSGSIZE, NULL) != 1)

12   err_quit("mq_receive error");

13 }

14 int

15 main(int argc, char **argv)

16 {

17  int i, nloop;

18  mqd_t mq1, mq2;

19  char buff[MSGSIZE];

20  pid_t childpid;

21  struct mq_attr attr;

22  if (argc != 2)

23   err_quit("usage: lat_pxmsg <#loops>");

24  nloop = atoi(argv[1]);

25  attr.mq_maxmsg = MAXMSG;

26  attr.mq_msgsize = MSGSIZE;

27  mq1 = Mq_open(Px_ipc_name(NAME1), O_RDWR | O_CREAT, FILE_MODE, &attr);

28  mq2 = Mq_open(Px_ipc_name(NAME2), O_RDWR | O_CREAT, FILE_MODE, &attr);

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

30   for(;;) { /* дочерний процесс */

31    if (Mq_receive(mq1, buff, MSGSIZE, NULL) != 1)

32     err_quit("mq_receive error");

33    Mq_send(mq2, buff, 1.0);

34   }

35   exit(0);

36  }

37  /* родительский процесс */

38  doit(mq1, mq2);

39  Start_time();

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

41   doit(mq1, mq2);

42  printf("latency: %.3f usecn", Stop_time() / nloop);

43  Kill(childpid, SIGTERM);

44  Mq_close(mq1);

45  Mq_close(mq2);

46  Mq_unlink(Px_ipc_name(NAMED);

47  Mq_unlink(Px_ipc_name (NAME2));

48  exit(0);

49 }

25-28 Создаются две очереди сообщений, каждая из которых используется для передачи данных в одну сторону. Хотя для очередей Posix можно указывать приоритет сообщений, функция mq_receive всегда возвращает сообщение с наивысшим приоритетом, поэтому мы не можем использовать лишь одну очередь для данного приложения.

Измерение задержки очередей сообщений System V

В листинге А.16 приведен текст программы измерения времени задержки для очередей сообщений System V.

Листинг А.16. Программа измерения времени задержки для очередей сообщений System V

//bench/lat_svmsg.c

1  #include "unpipc.h"

2  struct msgbuf p2child = { 1, { 0 } }; /* type = 1 */

3  struct msgbuf child2p = { 2, { 0 } }; /* type = 2 */

4  struct msgbuf inbuf;

5  void

6  doit(int msgid)

7  {

8   Msgsnd(msgid, &p2child, 0, 0);

9   if (Msgrcv(msgid, &inbuf, sizeof(inbuf.mtext), 2, 0) != 0)

10   err_quit("msgrcv error");

11 }

12 int

13 main(int argc, char **argv)

14 {

15  int i, nloop, msgid;

16  pid_t childpid;

17  if (argc != 2)

18   err_quit("usage: lat_svmsg <#loops>");

19  nloop = atoi(argv[1]);

20  msgid = Msgget(IPC_PRIVATE, IPC_CREAT | SVMSG_MODE);

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

22   for(;;) { /* дочерний процесс */

23    if (Msgrcv(msgid, &inbuf, sizeof(inbuf.mtext), 1, 0) != 0)

24     err_quit("msgrcv error");

25    Msgsnd(msgid, &child2p, 0, 0);

26   }

27   exit(0);

28  }

29  /* родительский процесс */

30  doit(msgid);

31  Start_time();

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

33   doit(msgid);

34  printf("latency: %.3f usecn", Stop_time() / nloop);

35  Kill(childpid, SIGTERM);

36  Msgctl(msgid, IPC_RMID, NULL);

37  exit(0);

38 }

Мы создаем одну очередь, по которой сообщения передаются в обоих направлениях. Сообщения с типом 1 передаются от родительского процесса дочернему, а сообщения с типом 2 — в обратную сторону. Четвертый аргумент при вызове msgrcv в функции doit имеет значение 2, что обеспечивает получение сообщений только данного типа. Аналогично в дочернем процессе четвертый аргумент msgrcv имеет значение 1.

ПРИМЕЧАНИЕ

В разделах 9.3 и 11.3 мы отмечали, что многие структуры, определенные в ядре, нельзя инициализировать статически, поскольку стандарты Posix.1 и Unix 98 гарантируют лишь наличие определенных полей в этих структурах, но не определяют ни их порядок, ни наличие других полей. В этой программе мы инициализируем структуру msgbuf статически, поскольку очереди сообщений System V гарантируют, что эта структура содержит поле типа сообщения long, за которым следуют передаваемые данные.

Программа измерения задержки интерфейса дверей

Пpoгрaммa измерения задержки для интерфейса дверей дана в листинге А.17. Дочерний процесс создает дверь и связывает с ней функцию server. Родительский процесс открывает дверь и вызывает door_call в цикле. В качестве аргумента передается 1 байт данных, и ничего не возвращается.

Листинг А.17. Программа измерения задержки интерфейса дверей

//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 usecn", 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 usecn", Stop_time() / nloop);

22  exit(0);

23 }

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

А.5. Синхронизация потоков: программы

Для измерения времени, уходящего на синхронизацию при использовании различных средств, мы создаем некоторое количество потоков (от одного до пяти, согласно табл. А.4 и А.5), каждый из которых увеличивает счетчик в разделяемой памяти большое количество раз, используя различные формы синхронизации для получения доступа к счетчику.

Взаимные исключения Posix

1 ... 113 114 115 116 117 118 119 120 121 ... 128
Перейти на страницу:
На этой странице вы можете бесплатно читать книгу UNIX: взаимодействие процессов - Уильям Стивенс.
Комментарии