如何找到哪个函数打开了套接字?

Posted

技术标签:

【中文标题】如何找到哪个函数打开了套接字?【英文标题】:How to find which function opened the socket? 【发布时间】:2013-06-01 08:33:35 【问题描述】:

我有一个进程在系统中 24*7 运行。最近有报道说这个进程打开了太多的套接字,已经用尽了它的最大限制。

root@typhoon-base-unit0:/root> lsof -p 681 | grep -i sock | wc -l
1018
root@typhoon-base-unit0:/root>

Strace 显示它每次迭代都会打开/关闭一个套接字,但突然有许多进程打开的套接字没有正确关闭。

socket(PF_NETLINK, SOCK_DGRAM, 11)      = 485
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 486
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 487
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 488
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 489
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 490
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 491
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 492
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 493
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 494
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 495
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 496
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 497
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 498
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 499
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 500
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 501
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 502
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 503
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 504
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 505
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 506
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 507
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 508
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 509
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 510
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 511
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 512
socket(0x1e /* PF_??? */, SOCK_SEQPACKET, 0) = 513
close(513)                              = 0
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 513
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 514
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 515
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 516
socket(0x1e /* PF_??? */, SOCK_SEQPACKET, 0) = 517
close(517)                              = 0
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 517
socket(PF_NETLINK, SOCK_DGRAM, 11)      = 518

我的问题是如何找出正在运行的进程的哪个函数创建了这个 PF_NETLINK 套接字?代码太大,无法手动跟踪所有可能的路径。有什么工具可以告诉我是哪个函数创建了这些 PF_NETLINK 套接字?

感谢任何帮助。

非常感谢。

【问题讨论】:

grep 命令是快速搜索大量文件的好命令。如果您使用的是 IDE,那么它很可能还具有“搜索所有文件”功能。 顺便问一下,我希望您没有以root 身份登录太频繁?这是一个相当大的安全漏洞。而是考虑使用sudo 运行真正需要它的程序。 Ehr,不是漏洞,但这是一个很大的安全风险。 没有工具可以在事后告诉您。你可能对 gdb 很幸运——在套接字系统调用上设置一个跟踪点,并告诉 gdb 打印一个回溯并在它到达跟踪点时继续。 @thejb,是的,有:使用 strace+。这真是太棒了,基本上是一个普通的 strace 但有回溯 【参考方案1】:

使用带有普通 strace 选项的 strace+ 来跟踪 socket() 系统调用。 它应该为您提供对进行调用的源代码行的堆栈跟踪。 使用它的步骤在这里: http://code.google.com/p/strace-plus/

【讨论】:

Strace+ 看起来真的很棒。但不幸的是,我的系统没有这个工具,所以无法使用它。我的错。但是非常感谢,因为我根本不知道这个工具。 strace+ 没有预先打包。您可以分 4 步安装它。只需按照上面链接中的步骤操作即可。【参考方案2】:

在调试器下运行它,并在socket() 中设置断点。当断点命中时,执行堆栈跟踪。

【讨论】:

您的建议奏效了。 GDB 在调用 socket() 时打印回溯。回溯很长,但幸运的是可以找出问题所在。非常感谢。

以上是关于如何找到哪个函数打开了套接字?的主要内容,如果未能解决你的问题,请参考以下文章

Winsock 发送函数

我必须将侦听套接字绑定到哪个主机?

在 Python 中打开 SSL 套接字连接

如何检测 Windows 中打开的套接字?

在哪个库中编写 writev 和其他在套接字上操作的函数,如 send 以及 .so 文件的位置在哪里

如何将每个 /proc/net/tcp 条目与每个打开的套接字匹配?