Чому довжина шляху розетки обмежена сотнею знаків?


18

У системах Unix шляхи імен зазвичай практично не обмежують довжину (ну, 4096 символів в Linux) ... за винятком шляхів файлів сокет, які обмежені приблизно 100 символами (107 символів в Linux ).

  • Перше питання: чому таке низьке обмеження?

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

  • Це рішення надійне чи мені просто пощастило?
  • Чи така поведінка специфічна для Linux чи це рішення може бути застосовно і до інших Unix?

Межа ще нижча (104) для нинішніх систем OpenBSD або Mac OS X 10.11.
триг

Важливим є те, що він повинен бути нижчим за 108, заради сумісності :)

AFAIK - це 108 символів на Linux. Перевірте /usr/include/$arch-linux-gnu/sys/un.h на своїй машині.
schaiba

@schaiba: 108 байт, що означає рядок 107 символів, що закінчується нульовим термінатором.
WhiteWinterWolf

Відповіді:


18

Сумісність з іншими платформами або сумісність із старими речами, щоб уникнути перевитрат під час використання snprintf()та strncpy().

Майкл Керріск пояснює у своїй книзі на сторінці 1165 - Глава 57, Розетки: Домен Unix:

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

Хлопці з Докера навіть посміялися з цього, адже деякі розетки були довжиною 110 символів:

Ось чому LINUX використовує розетку 108 char. Чи можна це змінити? Звичайно. І це причина, в першу чергу це обмеження було створено на старих Операційних системах:

Цитуючи відповідь:

Він повинен був відповідати простору, доступному в зручній структурі даних ядра.

Цитуючи "Проектування та впровадження операційної системи 4.4BSD" McKusick et. ін. (стор. 369):

Засоби управління пам'яттю обертаються навколо структури даних, що називається mbuf. Mbufs або буфери пам'яті мають довжину 128 байт, при цьому 100 або 108 байт цього простору відведено для зберігання даних.

Інші ОС (розетки домену Unix):


1
SUSv3 XNET мовчав, оскільки щодо цього немає єдиної думки.
fpmurphy

Чи є у вас якесь посилання на підтвердження своєї точки зору?

Дякую за цю відповідь. Чи надійно використовувати декілька файлів сокетів, що мають однакові імена відносно різних робочих каталогів (наприклад, створити файл сокетів, названий ./my.socketнижче каталогу A/, а інший файл сокета також названий ./my.socketнижче каталогу B/)? lsofне робить різниці між двома файлами сокетів, однак це все одно, здається, працює, але мені цікаво, чи це лише тому, що мені пощастило. Це було б гарним рішенням для створення файлів сокетів нижче шляху, який вже перевищує дозволений розмір.
WhiteWinterWolf

Пошук unix-сокетів на моєму lsof -U| grep amavisamavis-se 2708 zimbra 17u unix 0xffff8806c0a95400 0t0 310330411 /opt/zimbra/data/tmp/amavisd-zmq.sock

Так, я знаю, що це незвично, звідси і моє запитання тут;)! Для того, що я перевірив, відносні імена працюють, але це все ще здається дивним ... але це працює. Мій додаток не є загальносистемним, тому файли сокетів або зберігаються з усіма іншими даними програми в керованому користувачем місці, що вкрай бажано, але з потенційно занадто довгим шляхом, або я можу захаращувати /tmpбезліч неповторно названих невідтворених каталогів кожен що містить один файл сокета (абсолютно некрасиво, але портативно і безпечно).
WhiteWinterWolf

5

Щодо того, чому, nwildner вже написав чудову відповідь .

Тут я зупинюсь лише на тому, як і відносне використання шляху.

Внутрішньо, хоча файл сокета також можна шукати за назвою (я думаю), їх зазвичай шукають по inode. У Linux цей пошук забезпечується функцією, unix_find_socket_byinode()визначеною в net / unix / af_unix.c .

Це можна легко перевірити наступним чином:

  • Створіть два каталоги A / і B / .
  • Під кожним каталогом виконайте прослуховування процесу на файлах сокетів з однаковою назвою. З socatвами ви використовуєте таку команду, як:
$ socat UNIX-LISTEN:./my.sock -
  • Тепер обміняйте файли сокетів, перемістивши A / my.sock на B / і навпаки.
  • Відтепер, якщо клієнтська програма підключиться до A / my.sock, вона зв’яжеться з сервером B , а якщо він підключиться до B / my.sock, він зв’яжеться з сервером A (зауважте, що коли зв’язок закінчується, процес сервера може легально видаліть те, що він вважає власним файлом сокета).

Я перевірив цю поведінку на кількох системах Unix (Linux Debian, FreeBSD та OpenIndiana, щоб отримати певну різноманітність), тому така поведінка здається принаймні широко розповсюдженою, якщо не стандартною.

Абсолютні шляхи зазвичай використовуються як умова між клієнтом і серверними процесами, оскільки клієнтський процес може інакше не знати, як встановити початковий зв’язок із сервером.

Однак, якщо ця початкова комунікація не є проблемою, тому здається безпечним використовувати відносні шляхи для створення файлів сокетів, що дозволяє уникнути проблем із довжиною шляху, коли розташування файлу сокета безпосередньо не контролюється сервером.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.