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