Почему длина пути сокета ограничена сотней символов?

Почему длина пути сокета ограничена сотней символов?

В системах Unix имена путей обычно практически не имеют ограничений по длине (ну, 4096 символов в Linux)... за исключением путей к файлам сокетов, которые ограниченыоколо 100 символов(107 символов наЛинукс).

  • Первый вопрос:почему такое низкое ограничение?

Я проверил, что это ограничение можно обойти, изменив текущий рабочий каталог и создав в разных каталогах несколько файлов сокетов, использующих один и тот же путь ./myfile.sock: клиентские приложения, похоже, правильно подключаются к ожидаемым серверным процессам, хотя и lsofпоказывают, что все они прослушивают один и тот же путь к файлу сокета.

  • Надежен ли этот обходной путь или мне просто повезло?
  • Является ли это поведение специфичным для Linux или этот обходной путь применим и к другим Unix-системам?

решение1

Совместимость с другими платформами или совместимость со старыми версиями для предотвращения перегрузок при использовании snprintf()и strncpy().

Майкл Керриск объясняет вего книгавстраница 1165- Глава 57, Сокеты: домен Unix:

SUSv3 не определяет размер поля sun_path. Ранние реализации BSD использовали 108 и 104 байта, а одна современная реализация (HP-UX 11) использует 92 байта. Переносимые приложения должны кодировать с этим меньшим значением и использовать snprintf() или strncpy(), чтобы избежать переполнения буфера при записи в это поле.

Разработчики Docker даже посмеялись над этим, потому что некоторые сокеты были длиной 110 символов:

Вот почему LINUX использует 108-символьный сокет. Можно ли это изменить? Конечно. И вот почему изначально это ограничение было создано в старых операционных системах:

Цитирую ответ:

Это было сделано для того, чтобы соответствовать пространству, доступному в удобной структуре данных ядра.

Цитата из книги «Проектирование и реализация операционной системы 4.4BSD» МакКьюсика и др. (стр. 369):

Средства управления памятью вращаются вокруг структуры данных, называемой mbuf. Mbuf, или буферы памяти, имеют длину 128 байт, из которых 100 или 108 байт зарезервированы для хранения данных.

Другие ОС (сокеты домена Unix):

решение2

Что касается причины, то nwildner уже написалотличный ответ.

Здесь я сосредоточусь только на том, как и на использовании относительного пути.

Внутренне, хотя файл сокета также может быть найден по имени (я полагаю), они обычно ищутся по inode. В Linux этот поиск обеспечивается функцией, unix_find_socket_byinode()определенной вnet/unix/af_unix.c.

Это можно легко проверить следующим образом:

  • Создайте два каталогаА/иБ/.
  • В каждом каталоге заставьте процесс прослушивать файлы сокетов с тем же именем.socatвы бы использовали такую ​​команду:
$ socat UNIX-LISTEN:./my.sock -
  • Теперь обменяйтесь файлами сокетов, переместивА/мой.носоккБ/и наоборот.
  • С этого момента, если клиентское приложение подключается кА/мой.носокон свяжется с серверомБ, и если он подключается кB/мой.носокон свяжется с серверомА(однако следует отметить, что когда связь завершается, серверный процесс может законно удалить то, что он считает своим собственным файлом сокета).

Я проверил это поведение на нескольких системах Unix (Linux Debian, FreeBSD и OpenIndiana, чтобы получить некоторое разнообразие), так что такое поведение, по-видимому, является по крайней мере широко распространенным, если не стандартным.

Абсолютные пути обычно используются в качестве соглашения между клиентскими и серверными процессами, поскольку в противном случае клиентский процесс может не знать, как установить первоначальное соединение с сервером.

Однако если эта первоначальная коммуникация не является проблемой, то представляется безопасным использовать относительные пути для создания файлов сокетов, что позволяет избежать проблем с длиной пути, когда расположение файла сокета не контролируется напрямую процессом сервера.

Связанный контент