- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания UNIX: взаимодействие процессов - Уильям Стивенс
Шрифт:
Интервал:
Закладка:
//sunrpc/xdr1/example.c
1 #include "unpipc.h"
2 #include "example.h"
3 int
4 main(int argc, char **argv)
5 {
6 int size;
7 example foo;
8 size = RNDUP(sizeof(foo.a)) + RNDUP(sizeof(foo.b)) +
9 RNDUP(sizeof(foo.c[0])) * MAXC;
10 printf("size = %dn", size);
11 exit(0);
12 }
8-9 Макрос RNDUP определен в файле <rpc/xdr.h>. Он округляет аргумент к ближайшему кратному BYTES_PER_XDR_UNIT (4). Для массива фиксированного размера вычисляется размер каждого элемента, который затем умножается на количество элементов.
Проблема возникает в случае использования типов данных переменной длины. Если мы объявим stringd<10>, максимальный размер будет RNDUP(sizeof( int)) (для длины) плюс RNDUP(sizeof(char)*10) (для символов строки). Но мы не можем вычислить размер буфера, если максимальный размер не указан в объявлении переменной (например, float e<>). Лучше всего в этом случае выделять буфер с запасом, а потом проверять, не возвращают ли подпрограммы XDR ошибку (упражнение 16.5).
Пример: необязательные данные
Существуют три способа задания необязательных данных в файле XDR, примеры для всех приведены в листинге 16.17.
Листинг 16.17. Файл спецификации XDR, иллюстрирующий способы задания необязательных данных//sunrpc/xdr1/opt1.x
1 union optlong switch (bool flag) {
2 case TRUE:
3 long val;
4 case FALSE:
5 void;
6 };
7 struct args {
8 optlong arg1; /* объединение с булевским дискриминантом */
9 long arg2<1>; /* массив переменной длины с одним элементом */
10 long *arg3; /* указатель */
11 };
Объявление объединения с булевским дискриминантом1-8 Мы определяем объединение с ветвями FALSE и TRUE и структуру этого типа. Если флаг дискриминанта TRUE, за ним следует значение типа long; в противном случае за ним ничего не следует. После кодирования библиотекой XDR это объединение будет закодировано как:
■ 4 байта флага со значением 1 (TRUE) и 4 байта целочисленного значения либо
■ 4 байта флага со значением 0 (FALSE).
Объявление массива переменной длины9 Если мы указываем массив переменной длины с одним возможным элементом, он будет передан как:
■ 4 байта со значением 1 и 4 байта значения либо
■ 4 байта со значением 0.
Объявление указателя XDR10 Новый способ определения необязательных данных заключается в объявлении указателя. Он будет закодирован как:
■ 4 байта со значением 1 и 4 байта значения либо
■ 4 байта со значением 0
в зависимости от значения соответствующего указателя при кодировании данных. Если указатель ненулевой, используется первый вариант кодирования. Если указатель нулевой, получится второй вариант. Это удобный способ кодирования необязательных данных в случае, если в нашем коде имеется указатель на эти данные.
Важная деталь реализации, благодаря которой оба варианта дают одинаковый результат при кодировании, заключается в том, что значение TRUE равно 1, что совпадает с длиной массива переменной длины, когда в нем есть один элемент.
В листинге 16.18 приведен текст заголовочного файла, созданного программой rpcgen для данного файла спецификации.
Листинг 16.18. Заголовочный файл, получившийся в результате обработки листинга 16.17//sunrpc/xdr1/opt1.h
7 struct optlong {
8 bool_t flag;
9 union {
10 long val;
11 } optlong_u;
12 };
13 typedef struct optlong optlong;
14 struct args {
15 optlong arg1;
16 struct {
17 u_int arg2_len;
18 long *arg2_val;
19 } arg2;
20 long *arg3;
21 };
22 typedef struct args args;
14-21 Хотя все три аргумента кодируются одинаково, способы присваивания и получения их значений в языке С различны.
В листинге 16.19 приведен текст простой пpoгрaммы, устанавливающей значения всех трех аргументов так, что ни одно из полей long не кодируется.
Листинг 16.19. Ни одно из значений не будет закодировано//sunrpc/xdr1/opt1z.с
1 #include "unpipc.h"
2 #include "opt1.h"
3 int
4 main(int argc, char **argv)
5 {
6 int i;
7 XDR xhandle;
8 char *buff;
9 long *lptr;
10 args out;
11 size_t size;
12 out.arg1.flag = FALSE;
13 out.arg2.arg2_len = 0;
14 out.arg3 = NULL;
15 buff = Malloc(BUFFSIZE); /* Адрес должен быть кратен четырем */
16 xdrmem_create(&xhandle, buff, BUFFSIZE, XOR_ENCODE);
17 if (xdr_args(&xhandle, &out) != TRUE)
18 err_quit("xdr_args error");
19 size = xdr_getpos(&xhandle);
20 lptr = (long*)buff;
21 for (i = 0; i < size; i += 4)
22 printf("%ldn", (long) ntohl(*lptr++));
23 exit(0);
24 }
Присваивание значений12-14 Дискриминанту объединения присваивается значение FALSE, длина массива переменной длины устанавливается в 0, а указатель делается нулевым (NULL).
Выделение буфера и кодирование15-19 Мы выделяем буфер и кодируем структуру out в поток XDR.
Вывод содержимого буфера XDR20-22 Мы выводим содержимое буфера XDR по 4 байта, используя функцию ntohl (host-to-network long integer) для преобразования из порядка XDR big-endian в байтовый порядок узла. В результате получается именно то, что должно было быть помещено в буфер библиотекой XDR времени выполнения:
solaris % opt1z
0
0
0
Как мы и предполагали, каждому аргументу отводится 4 байта со значением О, указывающим на то, что за ним не следует никаких данных.
В листинге 16.20 приведена измененная версия программы, которая присваивает значения всем трем аргументам, кодирует их в поток XDR и выводит его содержимое.
Листинг 16.20. Присваивание значений аргументам из листинга 16.17//sunrpc/xdr1/opt1.c
1 #include "unpipc.h"
2 #include "opt1.h"
3 int
4 main(int argc, char **argv)
5 {
6 int i;
7 XOR xhandle;
8 char *buff;
9 long lval2, lval3, *lptr;
10 args out;
11 size_t size;
12 out.arg1.flag = TRUE;
13 out.arg1.optlong_u.val = 5;
14 lval2 = 9876;
15 out.arg2.arg2_len = 1;
16 out.arg2.arg2_val = &lval2;
17 lval3 = 123;
18 out.arg3 = &lval3;
19 buff = Malloc(BUFFSIZE); /* адрес должен быть кратен 4 */
20 xdrmem_create(&xhandle, buff, BUFFSIZE, XDR_ENCODE);
21 if (xdr_args(&xhandle, &out) != TRUE)
22 err_quit("xdr_args error");
23 size = xdr_getpos(&xhandle);
24 lptr = (long *) buff;
25 for (i = 0; i < size; i += 4)
26 printf("%ldn", (long) ntohl(*lptr++));
27 exit(0);
28 }
Присваивание значений12-18 Для присваивания значения объединению мы устанавливаем дискриминант в TRUE, а затем присваиваем значение полю long. Длину массива мы также сначала устанавливаем в 1. Указатель мы устанавливаем на соответствующее значение в памяти.
При запуске этой программы мы получим ожидаемые шесть 4-байтовых значений:
solaris % opt1
1 значение дискриминанта TRUE
5
1 длина массива переменной длины
9876
1 флаг для ненулевого указателя
123
Пример: обработка связного списка
Если осуществима передача необязательных данных, мы можем расширить возможности указателей в XDR и использовать их для кодирования и декодирования связных списков, содержащих произвольное количество элементов. В нашем примере используется связный список пар имя-значение. Соответствующий файл спецификации XDR приведен в листинге 16.21.
Листинг 16.21. Спецификация XDR для связного списка пар имя-значение//sunrpc/xdr1/opt2.x
1 struct mylist {
2 string name<>;
3 long value;
4 mylist *next;
5 };
6 struct args {
7 mylist *list;
8 };
1-5 Структура mylist содержит одну пару имя-значение и указатель на следующую структуру такого типа. Указатель в последней структуре списка будет нулевым.
В листинге 16.22 приведен текст заголовочного файла, созданного программой rpcgen из файла opt2.х.
Листинг 16.22. Заголовочный файл, созданный программой rpcgen//sunrpc/xdr1/opt2.h
7 struct mylist {
8 char *name;
9 long value;
10 struct mylist *next;