Так, 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-домену потребують очищення. Неабстрактний сокет фактично виділяє inode і створює запис у каталозі, який потрібно очистити в базовій файловій системі. Навпаки, подумайте про абстрактний сокет більше, ніж номер порту TCP або UDP. Звичайно, якщо ви прив’яжете порт TCP, а потім вийти, той порт TCP знову буде вільним. Але яке б 16-бітове число ви не використовували, все ще існує абстрактно і завжди. Простір імен номерів портів становить 1-65535 і ніколи не змінюється та не потребує очищення.
Тому просто подумайте про абстрактне ім'я сокета, як номер порту TCP або UDP, щойно вибране з набагато більшого набору можливих номерів портів, які, схоже, імена шляхів, але не є. Ви не можете прив’язати один і той же номер порту двічі (заборона SO_REUSEADDR
або SO_REUSEPORT
). Але закриття сокета (явно або неявно шляхом припинення) звільняє порт, не залишаючи нічого для очищення.