当我退出应用程序时,如何删除UNIX域套接字文件?

23
我有一个服务器应用程序,在特定路径下创建一个名为UNIX套接字,并通过bind()进行绑定。 我需要仅在故意关闭/停止应用程序时从应用程序代码内删除该套接字;否则它需要保持开启。如何实现? 谢谢! 编辑:考虑我从终端内启动和运行我的应用程序。
6个回答

31

你正在把这件事情搞得比必要的还要困难。把 unlink() 放在 bind() 之前就可以了。这是其他人都这么做的方式。(例如:BSD syslogd,其中一个经典的基于 Unix 域套接字的服务)


谢谢。我以为我必须在绑定之后进行操作,感谢您指明它必须在之前进行。 - Pheonix7
4
当服务器未运行时,您仍然可以在退出时进行取消链接以防止过时的套接字出现在目录列表中。但这纯粹是为了装饰效果。 - user2404501

6
如果您的应用程序有多个退出点,而且您不想修改每个退出点以调用清理例程,则可以使用“肮脏”的方法。
当套接字刚创建时,请使用atexit(3)注册清理例程。当应用程序正常终止时,将调用该例程(它只是一个对unlink(2)的调用)。但是如果应用程序被信号终止,则不会调用它。因此,如果您想在收到SIGINT和类似信号后进行清理,还需要正确设置信号处理程序。

好的,但文件仍然存在。我还需要从文件夹中删除该文件。 - Pheonix7
@Pheonix7,你检查了unlink的退出代码是否有错误吗? - gudok
当我使用Ctrl+C退出应用程序时,终端没有任何输出。当我重新启动应用程序时,会出现绑定错误:地址正在使用中。 - Pheonix7

4
您可以通过查看/proc/net/unix来检查套接字是否处于活动状态。然后,可以在cron中删除它,或在启动/重新启动应用程序之前删除它。
echo "active sockets in /path/"
cat /proc/net/unix | grep -Eo '/path/.*'

echo "all sockets in path including stale sockets"
ls -1F /path/ | egrep '=$' | sed 's/=$//'

echo "example command to remove stale sockets"
comm -1 -3 <(cat /proc/net/unix | grep -Eo '/path/.*' | sort)  <(ls -1F /path/ | egrep '=$' | sed 's/=$//' | sort) | xargs -n1 echo rm

1
如果您正在使用Linux,则可以使用抽象命名空间套接字:将sockaddr_un.sun_path中的第一个字节设置为\0,并保留在此数组中的其他字节。抽象套接字不会放置在文件系统上,这具有轻微的副作用。

参考资料

  1. https://gavv.net/articles/unix-socket-reuse/
  2. man 7 unix

抽象套接字

对于抽象套接字,套接字权限没有意义:在绑定抽象套接字时,进程umask(2)没有影响,并且更改对象的所有权和权限(通过fchown(2)和fchmod(2))对套接字的可访问性没有影响。

当所有对套接字的打开引用都关闭时,抽象套接字会自动消失。

抽象套接字命名空间是非便携式的Linux扩展。


0

只需执行

unlink("Path/to/Socket");

在退出程序之前。

但我从终端退出我的应用程序,那么在代码中我应该把unlink放在哪里? - Pheonix7

0

您可以通过简单的方式删除套接字文件:

unlink(path);

无论在何处编写程序退出程序,请检查其是否存在,并将其移除。

但是我从终端退出我的应用程序,那么在代码中我应该把unlink放在哪里? - Pheonix7
无论你从哪里退出应用程序,都没有关系,除非你说你按下了 Control-C 或其他什么。在这种情况下,你需要创建一个信号处理程序,在退出之前处理套接字。 - David Hoelzer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接