【问题标题】:Unwanted open sockets in the child process子进程中不需要的打开套接字
【发布时间】:2011-12-24 16:52:14
【问题描述】:

我有一个 PERL 脚本,它创建了很多套接字(大约 700 个套接字),然后对这些套接字进行处理。之后,它使用system(...) 命令启动另一个应用程序,该应用程序打开更多套接字(例如 800 个左右),但由于每个进程的套接字数量限制为1024,我超过了限制并且没有得到套接字号 1024 及以后的预期数据。

现在我的问题是:

  1. 系统命令是否使启动的应用程序继承所有打开的文件描述符/套接字?
  2. 如果上述问题的答案是肯定的,那么是否有其他方法可以启动另一个应用程序,使启动的应用程序不继承文件描述符?
  3. 如果 2. 的答案是否定的,那么有没有办法关闭子进程中所有继承的文件描述符?

【问题讨论】:

  • 假设这是一个类 UNIX 系统,每个用户的 fd 限制是多少?
  • 每个用户有限制吗?我不知道...每个进程的限制设置为 1024(所以 0 到 1023 工作正常,而 1024 失败)...
  • 我的意思是用户进程的资源限制可能低于系统的资源限制。你能在 system() 之前打印$^F 吗?你可以试试system('ulimit -n; exec your_command ...')看看当前的限制吗?
  • 我知道限制是 1024...关于如何增加这个限制的任何想法?

标签: perl sockets system parent-child


【解决方案1】:

看看perlvar $^F,它控制了哪些文件描述符被设置为close-on-exec。当您调用 system() 时,默认设置应该是关闭所有这些套接字描述符,但如果没有,可能 $^F 未设置为您想要的。在 Linux 系统上进行判断的一种非常快速且简单的方法是在您现有的 system() 调用之前尝试此调用:

system("ls -l /proc/self/fd");

ls 的输出将显示在执行“ls”命令时哪些文件处于打开状态。您很可能会看到只有标准输入、标准输出和标准错误(描述符 0、1 和 2)是打开的,但是如果您看到您的套接字描述符打开,我会尝试设置 $^F = 2 看看是否有帮助。

【讨论】:

  • 只是出于好奇的另一个问题...您知道如何在 C 中关闭子进程中打开的套接字吗?
  • 当然,假设您无法弄清楚为什么 close-on-exec 不起作用(我认为仍然是最好的第一种方法),您可以强制关闭除 stdin、stdout 和 stderr 之外的所有内容像这样:for (my $fd = 3; $fd < 1024; $fd++) { close(F) if open(F, "<&=$fd"); }
  • 啊,没有注意到你问题的“in C”部分,所以给了你 Perl 的答案。在 C 中,您可以使用 fcntl 调用来设置 close-on-exec,如下所示: fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
  • 刚刚注意到以前的 stackoverflow 讨论,您可能会觉得有用:stackoverflow.com/questions/1643304/…
  • 非常感谢!你太棒了!
猜你喜欢
  • 2013-10-19
  • 2017-07-27
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 2016-02-14
  • 1970-01-01
相关资源
最近更新 更多