Я пишу сервер сокетов домена Unix для Linux.
Особенность сокетов домена Unix, которую я быстро обнаружил, заключается в том, что при создании слушающего сокета Unix создается соответствующая запись файловой системы, закрытие сокета не удаляет ее. Более того, до тех пор, пока запись файловой системы не будет удалена вручную, невозможно снова bind()
перейти к тому же пути к сокету: bind()
завершается неудачно с EADDRINUSE
, если указанный путь уже существует в файловой системе.
Как следствие, запись в файловой системе сокета должна быть unlink()
зафиксирована при выключении сервера, чтобы избежать EADDRINUSE
при перезапуске сервера. Однако это не всегда возможно (например, сбой сервера). Большинство часто задаваемых вопросов, сообщений на форумах, веб-сайтов вопросов и ответов, которые я нашел, рекомендуют только unlink()
сокет перед вызовом bind()
. В этом случае, однако, становится желательно знать, привязан ли процесс к этому сокету, прежде чем unlink()
его установит.
Действительно, unlink()
установка сокета Unix, когда процесс все еще привязан к нему, а затем повторное создание слушающего сокета не вызывает никаких ошибок. В результате, однако, старый процесс сервера все еще работает, но недоступен: старый прослушивающий сокет «маскируется» новым. Такого поведения следует избегать.
В идеале, используя сокеты домена Unix, API сокетов должен демонстрировать такое же поведение «взаимного исключения», которое проявляется при привязке сокетов TCP или UDP: «Я хочу привязать сокет S к адресу A; если процесс уже привязан по этому адресу, просто пожалуйтесь! «К сожалению, это не так ...
Есть ли способ принудить к такому поведению «взаимного исключения»? Или, учитывая путь к файловой системе, есть ли способ узнать через API сокетов, есть ли у какого-либо процесса в системе сокет домена Unix, привязанный к этому пути? Должен ли я использовать примитив синхронизации, внешний по отношению к API сокетов (flock()
, ...)? Или я что-то упускаю?
Спасибо за ваши предложения.
Примечание. Сокеты Unix абстрактного пространства имен Linux, похоже, решают эту проблему, поскольку в unlink()
нет записи в файловой системе. Однако сервер, который я пишу, должен быть универсальным: он должен быть устойчивым к обоим типам сокетов домена Unix, поскольку я не несу ответственности за выбор адресов для прослушивания.