我正在为 Linux 编写一个 Unix 域套接字服务器。
我很快发现 Unix 域套接字的一个特点是,在创建侦听 Unix 套接字时会创建匹配的文件系统条目,关闭套接字并不会删除它。此外,在手动删除文件系统条目之前,不可能再次bind()
将套接字连接到同一路径:如果给出的路径已经存在于文件系统中,则会bind()
失败。EADDRINUSE
因此,套接字的文件系统条目需要unlink()
在服务器关闭时被 'ed 以避免EADDRINUSE
服务器重新启动。然而,这不能总是做到(即:服务器崩溃)。我发现的大多数常见问题解答、论坛帖子、问答网站都只是unlink()
在调用bind()
. 然而,在这种情况下,最好在unlink()
'ing 之前知道一个进程是否绑定到这个套接字。
实际上,unlink()
在进程仍绑定到 Unix 套接字时,然后重新创建侦听套接字不会引发任何错误。然而,结果是旧的服务器进程仍在运行但无法访问:旧的侦听套接字被新的“屏蔽”。必须避免这种行为。
理想情况下,使用 Unix 域套接字,套接字 API 应该具有与绑定 TCP 或 UDP 套接字时相同的“互斥”行为:“我想将套接字 S 绑定到地址 A;如果进程已经绑定到此地址,只是抱怨! ”不幸的是,事实并非如此......
有没有办法强制执行这种“互斥”行为?或者,给定一个文件系统路径,有没有办法通过套接字 API 知道系统上的任何进程是否有一个绑定到该路径的 Unix 域套接字?我应该使用套接字 API ( flock()
, ...) 外部的同步原语吗?还是我错过了什么?
感谢您的建议。
注意:Linux 的抽象命名空间 Unix 套接字似乎解决了这个问题,因为unlink()
. 但是,我正在编写的服务器旨在通用:它必须对两种类型的 Unix 域套接字都具有鲁棒性,因为我不负责选择侦听地址。