【问题标题】:How to know whether any process is bound to a Unix domain socket?如何知道任何进程是否绑定到 Unix 域套接字?
【发布时间】:2011-11-16 09:11:01
【问题描述】:

我正在为 Linux 编写一个 Unix 域套接字服务器。

我很快发现 Unix 域套接字的一个特点是,在创建侦听 Unix 套接字时会创建匹配的文件系统条目,而关闭套接字并不会删除它。此外,在手动删除文件系统条目之前,不可能再次将套接字bind() 指向同一路径:如果给出的路径已经存在于文件系统中,bind() 将失败并返回 EADDRINUSE

因此,套接字的文件系统条目需要在服务器关闭时为unlink()'ed,以避免在服务器重新启动时获得EADDRINUSE。但是,这并不总是可以完成(即:服务器崩溃)。我发现的大多数常见问题解答、论坛帖子、问答网站仅建议在调用bind() 之前向unlink() 套接字提供解决方法。但是,在这种情况下,最好在unlink()'ing 之前知道进程是否绑定到此套接字。

确实,unlink()'ing 一个 Unix 套接字,而一个进程仍然绑定到它,然后重新创建侦听套接字不会引发任何错误。然而,结果是旧的服务器进程仍在运行但无法访问:旧的侦听套接字被新的“屏蔽”。必须避免这种行为。

理想情况下,使用 Unix 域套接字,套接字 API 应该具有与绑定 TCP 或 UDP 套接字时相同的“互斥”行为:“我想将套接字 S 绑定到地址 A;如果一个进程已经绑定到这个地址了,只是抱怨!“不幸的是,事实并非如此......

有没有办法强制执行这种“互斥”行为?或者,给定一个文件系统路径,有没有办法知道,通过套接字 API,系统上的任何进程是否有一个绑定到该路径的 Unix 域套接字?我应该使用套接字 API 外部的同步原语 (flock(), ...) 吗?还是我错过了什么?

感谢您的建议。

注意:Linux 的抽象命名空间 Unix 套接字似乎解决了这个问题,因为unlink() 没有文件系统条目。但是,我正在编写的服务器旨在通用:它必须对两种类型的 Unix 域套接字都具有鲁棒性,因为我不负责选择监听地址。

【问题讨论】:

    标签: sockets unix-socket


    【解决方案1】:

    我知道我参加聚会很晚了,很久以前就已经回答了,但我只是在寻找其他东西时遇到了这个问题,我有一个替代建议。

    当您遇到从bind() 返回的EADDRINUSE 时,您可以输入连接到套接字的错误检查例程。如果连接成功,则有一个正在运行的进程至少还活着,可以完成accept()。这让我觉得这是实现您想要实现的目标的最简单和最便携的方式。它的缺点在于,最初创建 UDS 的服务器实际上可能仍在运行,但以某种方式“卡住”并且无法执行 accept(),因此该解决方案当然不是万无一失的,但它是一个步骤我认为朝着正确的方向发展。

    如果connect() 失败,则继续unlink() 端点并再次尝试bind()

    【讨论】:

    • 我已经对此进行了测试,它似乎可以像宣传的那样工作。太棒了!
    【解决方案2】:

    除了你已经考虑过的事情之外,我认为没有什么可以做的。看来你研究得很好。

    有一些方法可以确定套接字是否绑定到 unix 套接字(显然 lsof 和 netstat 会这样做),但它们非常复杂并且依赖于系统,以至于我怀疑它们是否值得努力处理您提出的问题。

    您确实提出了两个问题 - 处理与其他应用程序的名称冲突以及处理您自己应用程序的先前实例。

    根据定义,您的 pgm 的多个实例不应尝试绑定到同一路径,因此这可能意味着您一次只希望运行一个实例。如果是这种情况,您可以只使用标准的 pid 文件锁定技术,这样两个实例就不会同时运行。如果您无法获得锁,您不应该取消现有套接字的链接,甚至不应该运行。这也处理了服务器崩溃的情况。如果你能得到锁,那么你就知道你可以在绑定之前取消链接现有的套接字路径。

    您无法通过 AFAIK 来控制其他程序造成的冲突。文件权限并不完美,但如果您可以使用该选项,您可以将您的应用程序放在自己的用户/组中。如果存在现有的套接字路径并且您不拥有它,则不要取消链接并发出错误消息并让用户或系统管理员对其进行排序。使用配置文件使其易于更改 - 并可供客户使用 - 可能会起作用。除此之外,您几乎必须使用某种发现服务,除非这是一个非常关键的应用程序,否则这似乎是大材小用。

    总体而言,您可以放心,这实际上并不经常发生。

    【讨论】:

    • 感谢您的回答。使用传统的锁文件系统无疑是最安全的方法。此外,关于服务发现系统是否过度杀伤:具有讽刺意味的是,该服务器本身计划成为服务发现系统的一部分(服务“注册”系统似乎更合适)。这应该回答你的问题;-)
    猜你喜欢
    • 1970-01-01
    • 2010-11-25
    • 2014-07-09
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2011-12-23
    • 2014-06-02
    相关资源
    最近更新 更多