#define ifr_data ifr_ifru.ifru_data /* с использованием интерфейсом */
Прежде чем вызвать функцию
ioctl
, мы выделяем в памяти место для буфера и для структуры
ifconf
, а затем инициализируем эту структуру. Мы показываем это на рис. 17.1, предполагая, что наш буфер имеет размер 1024 байта. Третий аргумент функции
ioctl
— это указатель на нашу структуру
ifconf
.
Рис. 17.1. Инициализация структуры ifconf перед вызовом SIOCGIFCONF
Если мы предположим, что ядро возвращает две структуры
ifreq
, то при завершении функции
ioctl
мы можем получить ситуацию, представленную на рис. 17.2. Затененные области были изменены функцией
ioctl
. Буфер заполняется двумя структурами, и элемент
ifc_len
структуры
ifconf
обновляется, с тем чтобы соответствовать количеству информации, хранимой в буфере. Предполагается, что на этом рисунке каждая структура
ifreq
занимает 32
байта.
Рис. 17.2. Значения, возвращаемые в результате вызова SIOCGIFCONF
Указатель на структуру
ifreq
также используется в качестве аргумента оставшихся функций
ioctl
интерфейса, показанных в табл. 17.1, которые мы описываем в разделе 17.7. Отметим, что каждая структура
ifreq
содержит объединение (
union
), а директивы компилятора
#define
позволяют непосредственно обращаться к полям объединения по их именам. Помните о том, что в некоторых системах в объединение
ifr_ifru
добавлено много зависящих от реализации элементов.
17.6. Функция get_ifi_info
Поскольку многим программам нужно знать обо всех интерфейсах системы, мы разработаем нашу собственную функцию
get_ifi_info
, возвращающую связный список структур — по одной для каждого активного в настоящий момент интерфейса. В этом разделе мы покажем, как эта функция реализуется с помощью вызова
SIOCGIFCONF
функции
ioctl
, а в главе 18 мы создадим ее другую версию, использующую маршрутизирующие сокеты.
Поиск по всему дереву исходного кода BSD/OS 2.1 показывает, что 12 программ выполняют вызов SIOCGIFCONF функции ioctl для определения присутствующих интерфейсов.
Сначала мы определяем структуру
ifi_info
в новом заголовочном файле, который называется
unpifi.h
, показанном в листинге 17.2.
Листинг 17.2. Заголовочный файл unpifi.h
//ioctl/unpifi.h
1 /* Наш собственный заголовочный файл для программ, которым требуется
2 информация о конфигурации интерфейса. Включаем его вместо "unp.h". */
3 #ifndef __unp_ifi_h
4 #define __unp_ifi_h
5 #include "unp.h"
6 #include <net/if.h>
7 #define IFI_NAME 16 /* то же, что и IFNAMSIZ в заголовке <net/if.h> */
8 #define IFI_HADDR 8 /* с учетом 64-битового интерфейса EUI-64 в будущем */
9 struct ifi_info {
10 char ifi_name[IFI_NAME]; /* имя интерфейса, заканчивается