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