我通过LD_PRELOAD变量插入JVM。
基本上,我想构建一个虚拟路由表(VRT)。在bind()调用中,我修改了我选择的IP地址和端口参数(我保存在VRT中)。此外,我将套接字描述符(bind()的第一个参数)添加到链接列表。 (直到这个阶段,socket有一个sin_family类型的AF_INET6。)
现在当套接字关闭(close())时,我想删除虚拟路由表条目。所以,我检查一下我们试图关闭的套接字描述符是否存储在链接列表中。如果是,则表示其记录存在于VRT中,因此我应该在关闭套接字之前删除VRT条目。我面临的问题是,在这个阶段,相同的套接字描述符的sin_family值为1(我不知道它代表什么)而不是10(AF_INET6,bind()期间的值)。此外,我尝试在此阶段打印套接字描述符的IP地址和端口,但它是垃圾。
我不知道我错过了什么。
更新: 我的代码没有问题。由于JVM的以下行为(我通过strace追踪)
,因此出现了异常现象9722 socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 12
...(receive messages)...
9722 dup2(11, 12) = 12 (?!?)
9722 close(12) = 0
JVM在我们的套接字上复制了另一个文件描述符,因为它的sin_family在close()上没有正确显示。奇怪!
答案 0 :(得分:0)
sin_family == 1
是AF_UNIX
,即管道或域名套接字。
你确定它真的是“相同的”套接字描述符吗?你怎么识别它?它的整数值仅对进程唯一。
如果您LD_PRELOAD
的过程让孩子们离开,那么他们也会使用与父母一样的描述符,而他们的兄弟姐妹和孩子都会使用你的钩子。
因此,要解决这种歧义,请在挂钩getpid()
代码中使用bind()
获取PID,并将PID添加到您为此套接字存储的密钥中。
dup2(int fdOld, int fdNew)
在制作fdNew
副本之前关闭fdOld
。但你不能将调用挂钩close()
,我想: - (。