Да, linux автоматически «очищает» абстрактные сокеты до такой степени, что очистка даже имеет смысл. Вот минимальный рабочий пример, с помощью которого вы можете проверить это:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
int
main(int argc, char **argv)
{
int s;
struct sockaddr_un sun;
if (argc != 2 || strlen(argv[1]) + 1 > sizeof(sun.sun_path)) {
fprintf(stderr, "usage: %s abstract-path\n", argv[0]);
exit(1);
}
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
perror("socket");
exit(1);
}
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path + 1, argv[1]);
if (bind(s, (struct sockaddr *) &sun, sizeof(sun))) {
perror("bind");
exit(1);
}
pause();
}
Запустите эту программу как ./a.out /test-socket &
, затем запустите ss -ax | grep test-socket
, и вы увидите, что сокет используется. Тогда kill %./a.out
и ss -ax
покажет сокет ушел.
Однако причина, по которой вы не можете найти эту очистку в какой-либо документации, заключается в том, что она на самом деле не очищает в том же смысле, что неабстрактные сокеты домена unix требуют очистки. Неабстрактный сокет фактически выделяет индекс и создает запись в каталоге, которую необходимо очистить в базовой файловой системе. Напротив, думайте об абстрактном сокете больше как номер порта TCP или UDP. Конечно, если вы связываете порт TCP и затем выходите, этот порт TCP снова будет свободен. Но какой бы 16-битный номер вы ни использовали, он существует абстрактно и всегда существует. Пространство имен номеров портов - 1-65535 и никогда не изменяется и не нуждается в очистке.
Так что просто подумайте об абстрактном имени сокета, как о номере порта TCP или UDP, просто выберите из гораздо большего набора возможных номеров портов, которые выглядят как пути, но не являются таковыми. Вы не можете связать один и тот же номер порта дважды (за исключением SO_REUSEADDR
или SO_REUSEPORT
). Но закрытие сокета (явным или неявным путем завершения) освобождает порт, и нечего очищать.