#c #sockets #unix #solaris #portability
#c #сокеты #unix #solaris #переносимость
Вопрос:
Я наткнулся на своеобразную разницу между сокетами Solaris 10 и другими сокетами Linux / * NIX. Пример:
int temp1, rc;
temp1 = 16*1024*1024; /* from config, a value greater than system limit */
rc = setsockopt( sd, SOL_SOCKET, SO_RCVBUF, amp;temp1, sizeof(temp1);
Приведенный выше код будет работать rc == 0
на всех системах — Linux, HP-UX и AIX — за исключением Solaris 10. Другие системы автоматически усекают предоставленное значение до допустимого максимума. Solaris 10 справедливо завершается ошибкой, errno == ENOBUFS
указывая на ошибку конфигурации.
После некоторого обсуждения было решено, что, поскольку конкретное приложение является критичным, вместо сбоя оно должно продолжать работать как можно более корректно:
- Создайте предупреждение в файле журнала о несоответствии конфигурации (легко, добавьте проверку с помощью
getsockopt()
) и - Попробуйте установить максимальный размер буфера (чтобы получить максимально возможную производительность).
# 2 — это то, что я застрял. Во всех системах, отличных от Solaris, мне не нужно ничего делать: сокеты уже делают это за меня.
Но на Solaris я в растерянности, что делать. Я реализовал некоторую тривиальную дихотомию вокруг (setsockopt(...) == -1 amp;amp; errno == ENOBUFS)
условия определения максимального размера буфера, но это выглядит некрасиво. (У меня также нет контекста для сохранения результатов поиска: поиск пришлось бы повторять для каждого соединения с такой плохой конфигурацией. Глобальные переменные проблематичны, поскольку код находится внутри разделяемой библиотеки и используется из приложения MT.)
Есть ли в Solaris 10 какой-либо лучший способ определить максимально допустимый размер буфера с помощью sockets API?
Есть ли какой-либо способ сообщить Solaris’sockets API усекать значение, как это делают другие системы?
Комментарии:
1. Долгое время не пользовался solaris — можете ли вы получить tcp_max_buf из /dev / tcp? В противном случае какой-нибудь взлом с помощью «ndd -get /dev/ tcp tcp_max_buf» и каким-то образом передайте ее в pgm.
2. Да … Если OpenSolaris имеет какое-либо отношение, то это кажется невозможным : tcps_max_buf только считывается, но никогда не используется как возврат функции или не записывается в переменную. К базовому
tcps_propinfo_tbl
файлу также можно получить доступ только целиком.3. Довольно иронично для (бывшего) системного программиста оказаться жертвой строго совместимого интерфейса…
4. На самом деле проблема в том, что, похоже, нет способа получить информацию, необходимую для работы с совместимым интерфейсом. Если посмотреть на это немного подробнее, кажется, что вы были не первыми, кто столкнулся с этим.
Ответ №1:
На данный момент у меня нет доступа к системе Solaris 10, но, согласно документации Oracle, вы можете использовать ndd
утилиту для запроса (и установки) настроенных максимальных размеров буфера для TCP и UDP:
$ ndd -get /dev/tcp tcp_max_buf
$ ndd -get /dev/udp udp_max_buf
Я не в курсе C API, но, возможно, какие ndd
виды использования доступны?
Комментарии:
1. Я
truss
отредактировал ее, и она переходит к/dev/tcp
, а затем запускает пару специфичных для потоковioctl()
вызовов: I_CANPUT и I_STR. И I_STR, по-видимому, используется для отправки сообщения в модуль stream. И это было, когда заканчивался POSIX — и начиналось что-то, полностью специфичное для Solaris и недостаточно документированное (не удалось найти никакой документации).2. Исходный код здесь показывает , что это не общедоступный интерфейс. Например,
mod_prop_info_t
даже не объявлено в/usr/include
. На данный момент кажется, что это невыполнимо.