Книга: UNIX: взаимодействие процессов

Буфер результатов слишком мал

Буфер результатов слишком мал

Когда мы рассказывали о функции door_call, мы отметили, что если буфер результатов оказывается слишком мал, библиотека дверей осуществляет автоматическое выделение нового буфера. Сейчас мы покажем это на примере. В листинге 15.4 приведен текст новой программы-клиента, которая представляет собой измененную версию листинга 15.2.

Листинг 15.4. Вывод адреса полученного результата

//doors/client2.c
1  #include "unpipc.h"
2  int
3  main(int argc, char **argv)
4  {
5   int fd;
6   long ival, oval;
7   door_arg_t arg;
8   if (argc != 3)
9    err_quit("usage: client2 <server-pathname> <integer-value>");
10  fd = Open(argv[1], O_RDWR); /* открываем дверь */
11  /* подготовка аргументов и указателя на результат */
12  ival = atol(argv[2]);
13  arg.data_ptr = (char *) &ival; /* аргументы-данные */
14  arg.data_size = sizeof(long); /* объем данных */
15  arg.desc_ptr = NULL;
16  arg.desc_num = 0;
17  arg.rbuf = (char *) &oval; /* возвращаемые данные */
18  arg.rsize = sizeof(long); /* объем возвращаемых данных */
19  /* вызов процедуры сервера и вывод результата */
20  Door_call(fd, &arg);
21  printf("&oval = %p, data_ptr = %p, rbuf = %p, rsize = %dn",
22   &oval, arg.data_ptr, arg.rbuf, arg.rsize);
23  printf("result: %ldn", *((long *) arg.data_ptr));
24  exit(0);
25 }

19-22 В этой версии программы на экран выводится адрес переменной oval, содержимое указателя data_ptr, который должен указывать на возвращаемые функцией door_call данные, и адрес и размер приемного буфера (rbuf и rsize).

Запустим эту программу, не изменяя размер приемного буфера по сравнению с листингом 15.2. Мы ожидаем, что data_ptr и rbuf будут указывать на переменную oval и rsize будет иметь значение 4 (4 байта в буфере). И действительно, вот что мы видим:

solaris % client2 /tmp/server2 22
&oval = effff740, data_ptr = effff740, rbuf = effff740, rsize = 4
result: 484

Изменим только одну строку в листинге 15.4, уменьшив размер буфера клиента до одного байта. Новый вариант строки 18 будет иметь вид:

arg.rsize = sizeof(long) – 1; /* размер буфера данных */

Запустим новую программу и увидим, что библиотека автоматически выделила место под новый буфер результатов и data_ptr теперь указывает на новый буфер:

solaris % client3 /tmp/server3 33
&oval = effff740, data_ptr = ef620000, rbuf = ef620000, rsize = 4096
result: 1089

Размер выделенного буфера равен 4096 байт, что совпадает с размером страницы в данной системе, который мы узнали в разделе 12.6. Этот пример показывает, что следует всегда обращаться к результатам через указатель data_ptr, а не через переменные, адреса которых были переданы в rbuf. В нашем примере к результату типа «длинное целое» следует обращаться как *(long*)arg.data_ptr, а не oval (что мы делали в листинге 15.2).

Новый буфер выделяется вызовом mmap и может быть возвращен системе с помощью munmap. Клиент может повторно использовать этот буфер при новых вызовах door_call.

Оглавление книги


Генерация: 1.343. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз