2. Что произойдет в листинге 16.6, если процесс сервера завершится преждевременно и дочерний процесс получит признак конца файла, но не уведомит об этом родительский процесс?
3. Что произойдет в листинге 16.6, если родительский процесс непредвиденно завершится до завершения дочернего процесса, и дочерний процесс затем считает конец файла на сокете?
4. Что произойдет в листинге 16.7, если мы удалим следующие две строки:
if (n == 0)
goto done; /* функция connect завершилась немедленно */
5. В разделе 16.3 мы сказали, что возможна ситуация, когда данные для сокета придут раньше, чем завершится функция
connect
. Когда это может случиться?
Глава 17
Операции функции ioctl
17.1. Введение
Функция
ioctl
традиционно являлась системным интерфейсом, используемым для всего, что не входило в какую-либо другую четко определенную категорию. POSIX постепенно избавляется от функции
ioctl
, создавая заменяющие ее функции-обертки и стандартизуя их функциональность. Например, доступ к интерфейсу терминала Unix традиционно осуществлялся с помощью функции
ioctl
, но в POSIX были созданы 12 новых функций для терминалов:
tcgetattr
для получения атрибутов терминала,
tcflush
для опустошения буферов ввода или вывода, и т.д. Аналогичным образом POSIX заменяет одну сетевую функцию
ioctl
: новая функция
sockatmark
(см. раздел 24.3) заменяет команду
SIOCATMARK ioctl
. Тем не менее прочие сетевые команды
ioctl
остаются не стандартизованными и могут использоваться, например, для получения информации об интерфейсе и обращения к таблице маршрутизации и кэшу ARP (Address Resolution Protocol — протокол разрешения адресов).
В этой главе представлен обзор команд функции
ioctl
, имеющих отношение к сетевому программированию, многие из которых зависят от реализации. Кроме того, некоторые реализации, включая системы, происходящие от 4.4BSD и Solaris 2.6, используют сокеты домена
AF_ROUTE
(маршрутизирующие сокеты) для выполнения многих из этих операций. Маршрутизирующие сокеты мы рассматриваем в главе 18.
Обычно сетевые программы (как правило, серверы) используют функцию
ioctl
для получения информации обо всех интерфейсах узла при запуске программы, с тем чтобы узнать адрес интерфейса, выяснить, поддерживает ли интерфейс широковещательную передачу, многоадресную передачу и т.д. Для возвращения этой информации мы разработали нашу собственную функцию. В этой главе мы представляем ее реализацию с применением функции
ioctl
, а в главе 18 — другую реализацию, использующую маршрутизирующие сокеты.
17.2. Функция ioctl
Эта функция работает с открытым файлом, дескриптор которого передается через аргумент
fd
.
#include <unistd.h>
int ioctl(int <i>fd</i>, int <i>request</i>, ... /* void *<i>arg</i> */ );
<i>Возвращает: 0 в случае успешного выполнения, -1 в случае ошибки</i>
Третий аргумент всегда является указателем, но тип указателя зависит от аргумента
request
.
ПРИМЕЧАНИЕ
В 4.4BSD второй аргумент имеет тип unsigned long вместо int, но это не вызывает проблем, поскольку в заголовочных файлах определены константы, используемые для данного аргумента. Пока прототип функции подключен к программе, система будет обеспечивать правильную типизацию.
Некоторые реализации определяют третий аргумент как неопределенный указатель (void*), а не так, как он определен в ANSI С.
Не существует единого стандарта заголовочного файла, определяющего прототип функции для ioctl, поскольку он не стандартизован в POSIX. Многие системы определяют этот прототип в файле <unistd.h>, как это показываем мы, но традиционные системы BSD определяют его в заголовочном файле <sys/ioctl.h>.
Мы можем разделить аргументы
request
, имеющие отношение к сети, на шесть категорий:
■ операции с сокетами;
■ операции с файлами;
■ операции с интерфейсами;
■ операции с кэшем ARP;
■ операции с таблицей маршрутизации;
■ операции с потоками (см. главу 31).
Помимо того, что, как показывает табл. 7.9, некоторые операции
ioctl
перекрывают часть операций
fcntl
(например, установка неблокируемого сокета), существуют также некоторые операции, которые с помощью функции
ioctl
можно задать более чем одним способом (например, смена групповой принадлежности сокета).
В табл. 17.1 перечислены аргументы request вместе с типами данных, на которые должен указывать адрес
arg
. В последующих разделах эти вызовы рассматриваются более подробно.
Таблица 17.1. Обзор сетевых вызовов ioctl
Категория | request | Описание | Тип данных |
Сокет | SIOCATMARK | Находится ли указатель чтения сокета на отметке внеполосных данных | int |
SIOCSPGRP | Установка идентификатора процесса или идентификатора группы процессов для сокета | int |
SIOCGPGRP | Получение идентификатора процесса или идентификатора группы процессов для сокета | int |
Файл | FIONBIO | Установка/сброс флага отсутствия блокировки | int |
FIOASYNC | Установка/сброс флага асинхронного ввода-вывода | int |
FIONREAD | Получение количества байтов в приемном буфере | int |
FIOSETOWN | Установка идентификатора процесса или идентификатора группы процессов для файла | int |
FIOGETOWN | Получение идентификатора процесса или идентификатора группы процессов для файла | int |
Интерфейс | SIOCGIFCONF | Получение списка всех интерфейсов | struct ifconf |
SIOCSIFADDR | Установка адреса интерфейса | struct ifreq |
SIOCGIFADDR | Получение адреса интерфейса | struct ifreq |
SIOCSIFFLAGS | Установка флагов интерфейса | struct ifreq |
SIOCGIFFLAGS | Получение флагов интерфейса | struct ifreq |
SIOCSIFDSTADDR | Установка адреса типа «точка-точка» | struct ifreq |
SIOCGIFDSTADDR | Получение адреса типа «точка-точка» | struct ifreq |
SIOCGIFBRDADDR | Получение широковещательного адреса | struct ifreq |
SIOCSIFBRDADDR | Установка широковещательного адреса | struct ifreq |
SIOCGIFNETMASK | Получение маски подсети | struct ifreq |
SIOCSIFNETMASK | Установка маски подсети | struct ifreq |
SIOCGIFMETRIC | Получение метрики интерфейса | struct ifreq |
SIOCSIFMETRIC | Установка метрики интерфейса | struct ifreq |
SIOCxxx | (Множество вариантов в зависимости от реализации) | |
ARP | SIOCSARP | Создание/модификация элемента ARP | struct arpreq |
SIOCGARP | Получение элемента ARP | struct arpreq |
SIOCDARP | Удаление элемента ARP | struct arpreq |
Маршрутизация | SIOCADDRT | Добавление маршрута | struct rtentry |
SIOCDELRT | Удаление маршрута | struct rtentry |
Потоки | I_xxx | (См. раздел 31.5) | |