当我们在Unix中执行fork时,打开的文件句柄被继承,如果我们不需要使用它们,我们应该关闭它们。但是,当我们使用库时,文件句柄可能会被打开,而我们没有访问句柄的权限。我们如何检查这些打开的文件句柄?
0ve6wy6x1#
在Linux中,你可以检查/proc/<pid>/fd目录-对于每个打开的fd,都会有一个名为handle的文件。我几乎可以肯定这条路是不可移动的。或者,您可以使用lsof-根据man lsof,可用于Linux,AIX,FreeBSD和NetBSD。
/proc/<pid>/fd
lsof
man lsof
fjnneemd2#
你可以从一个shell:第一个月其中 PID 是进程的PID。
kq0g1dla3#
如果库正在打开你不知道的文件,你怎么知道它们在分叉后不需要它们?未导出的句柄是一个内部库细节,如果库希望关闭它们,它将注册一个atfork()处理程序来关闭它们。在一些代码后面来回走动,在背后关闭其文件句柄将导致微妙的难以调试的问题,因为当库试图使用它知道它正确打开但没有关闭的句柄时,它会意外地出错。
r1zk6ea14#
正如@Louis Gerbarg的回答中提到的,库可能希望文件句柄在fork()上保持打开(毕竟,它应该是父进程的几乎相同的副本)。大多数人遇到的问题是在exec()上,它经常跟随在fork()之后。这里,正确的解决方案是让创建句柄的库将它们标记为close-on-exec(FD_CLOEXEC)。在多线程程序使用的库中,在创建文件句柄的库和在其上设置FD_CLOEXEC之间存在竞争条件(另一个线程可以在两个操作之间执行fork())。为了解决这个问题,在Linux内核中引入了O_CLOEXEC。
fork()
exec()
FD_CLOEXEC
O_CLOEXEC
siv3szwd5#
首先,您不需要非常关心您不知道的打开的文件描述符。如果你知道你不会再写信给他们,关闭他们是一个好主意,也不会伤害-你只是做了一个fork(),毕竟,fds是打开两次。但同样,如果你让它们打开,它们也不会打扰你--毕竟,你不知道它们,你大概不会随意给它们写信。至于你的第三方库将做什么,这是一个有点折腾的方式。有些人可能不希望遇到使用fork()的情况,并且可能会意外地从两个进程写入同一个fd,而没有任何同步。其他人可能不希望你关闭他们的fds。你得检查一下。这就是为什么在库中随机打开文件描述符而不将其交给调用者管理是一个坏主意的原因。尽管如此,本着回答最初问题的精神,没有特别好的方法。您可以在文件描述符上调用dup()或dup2();如果它被关闭,调用将失败,并返回EBADF。所以你可以说:
dup()
dup2()
EBADF
int newfd = dup(oldfd); if (newfd > 0) { close(newfd); close(oldfd); }
字符串但是在这一点上,您最好首先说close(oldfd),并忽略任何EBADF。假设您仍然希望采取关闭所有内容的核心选项,那么您需要找到可能打开的文件描述符的最大数量。假设1比65,535不是个好主意。首先,fds从0开始,当然,也没有定义特定的上限。为了便于移植,POSIX的sysconf(_SC_OPEN_MAX)应该告诉您,在任何正常的POSIX系统上,尽管严格地说它是可选的。如果你感觉偏执,检查返回值-1,尽管在这一点上,你大多不得不依靠一个硬编码的值(1024应该是好的,除非你在做一些非常奇怪的事情)。或者,如果您对特定于Linux没意见,您可以在/proc中查找。别忘了不要关闭fds 0、1和2 --这真的会混淆事情。
close(oldfd)
sysconf(_SC_OPEN_MAX)
3npbholx6#
我同意其他人所说的关闭随机文件是危险的。您可能最终会为所有第三方工具提交一些非常有趣的bug报告。也就是说,如果你知道你不需要打开这些文件,你总是可以遍历所有有效的文件描述符(1到65535,IIRC),并关闭所有你不认识的文件。
jyztefdp7#
合理的库总是具有释放任何资源的功能(例如,文件句柄)。
wko9yo5t8#
只是一个链接,但它似乎很有用:How many open files?在netadmintools.com.它似乎使用/proc调查来了解进程的打开文件,不确定这是否是唯一的方法,或者是否有API。解析文件中的这种类型的信息可能有点.另外,/proc也可能被弃用,需要检查一下。
disbfnqx9#
这不是设计问题吗?在初始化打开这些文件的库之前,您的进程是否可以进行fork?
9条答案
按热度按时间0ve6wy6x1#
在Linux中,你可以检查
/proc/<pid>/fd
目录-对于每个打开的fd,都会有一个名为handle的文件。我几乎可以肯定这条路是不可移动的。或者,您可以使用
lsof
-根据man lsof
,可用于Linux,AIX,FreeBSD和NetBSD。fjnneemd2#
你可以从一个shell:
第一个月
其中 PID 是进程的PID。
kq0g1dla3#
如果库正在打开你不知道的文件,你怎么知道它们在分叉后不需要它们?未导出的句柄是一个内部库细节,如果库希望关闭它们,它将注册一个atfork()处理程序来关闭它们。在一些代码后面来回走动,在背后关闭其文件句柄将导致微妙的难以调试的问题,因为当库试图使用它知道它正确打开但没有关闭的句柄时,它会意外地出错。
r1zk6ea14#
正如@Louis Gerbarg的回答中提到的,库可能希望文件句柄在
fork()
上保持打开(毕竟,它应该是父进程的几乎相同的副本)。大多数人遇到的问题是在
exec()
上,它经常跟随在fork()
之后。这里,正确的解决方案是让创建句柄的库将它们标记为close-on-exec(FD_CLOEXEC
)。在多线程程序使用的库中,在创建文件句柄的库和在其上设置
FD_CLOEXEC
之间存在竞争条件(另一个线程可以在两个操作之间执行fork()
)。为了解决这个问题,在Linux内核中引入了O_CLOEXEC
。siv3szwd5#
首先,您不需要非常关心您不知道的打开的文件描述符。如果你知道你不会再写信给他们,关闭他们是一个好主意,也不会伤害-你只是做了一个fork(),毕竟,fds是打开两次。但同样,如果你让它们打开,它们也不会打扰你--毕竟,你不知道它们,你大概不会随意给它们写信。
至于你的第三方库将做什么,这是一个有点折腾的方式。有些人可能不希望遇到使用fork()的情况,并且可能会意外地从两个进程写入同一个fd,而没有任何同步。其他人可能不希望你关闭他们的fds。你得检查一下。这就是为什么在库中随机打开文件描述符而不将其交给调用者管理是一个坏主意的原因。
尽管如此,本着回答最初问题的精神,没有特别好的方法。您可以在文件描述符上调用
dup()
或dup2()
;如果它被关闭,调用将失败,并返回EBADF
。所以你可以说:字符串
但是在这一点上,您最好首先说
close(oldfd)
,并忽略任何EBADF。假设您仍然希望采取关闭所有内容的核心选项,那么您需要找到可能打开的文件描述符的最大数量。假设1比65,535不是个好主意。首先,fds从0开始,当然,也没有定义特定的上限。为了便于移植,POSIX的
sysconf(_SC_OPEN_MAX)
应该告诉您,在任何正常的POSIX系统上,尽管严格地说它是可选的。如果你感觉偏执,检查返回值-1,尽管在这一点上,你大多不得不依靠一个硬编码的值(1024应该是好的,除非你在做一些非常奇怪的事情)。或者,如果您对特定于Linux没意见,您可以在/proc中查找。别忘了不要关闭fds 0、1和2 --这真的会混淆事情。
3npbholx6#
我同意其他人所说的关闭随机文件是危险的。您可能最终会为所有第三方工具提交一些非常有趣的bug报告。
也就是说,如果你知道你不需要打开这些文件,你总是可以遍历所有有效的文件描述符(1到65535,IIRC),并关闭所有你不认识的文件。
jyztefdp7#
合理的库总是具有释放任何资源的功能(例如,文件句柄)。
wko9yo5t8#
只是一个链接,但它似乎很有用:How many open files?在netadmintools.com.它似乎使用/proc调查来了解进程的打开文件,不确定这是否是唯一的方法,或者是否有API。解析文件中的这种类型的信息可能有点.另外,/proc也可能被弃用,需要检查一下。
disbfnqx9#
这不是设计问题吗?在初始化打开这些文件的库之前,您的进程是否可以进行fork?