【问题标题】:Threads/Sockets limits in LinuxLinux 中的线程/套接字限制
【发布时间】:2011-11-26 17:33:39
【问题描述】:

首先:对不起我的英语。 伙计们,我在使用 POSIX 套接字和/或 pthread 时遇到了麻烦。我正在嵌入式设备(ARM9 CPU)上开发。在设备上将工作多线程 tcp 服务器。它将能够处理大量传入连接。服务器从客户端获取连接并增加计数器变量(无符号整数计数器)。客户端例程将在单独的线程中运行。所有客户端都将使用 1 个单例类实例(在此类中将打开和关闭相同的文件)。客户端处理文件,然后客户端线程关闭连接套接字,并调用 pthread_exit()。 所以,我的 tcp 服务器不能处理超过 250 个线程(计数器 = 249 +1(服务器线程)。我得到“资源暂时不可用”。有什么问题?

【问题讨论】:

  • 检查ulimit 看看有什么限制,我猜你可能已经达到了。
  • 我查了一下,ulimit说我可以使用900+(可能是994)线程。
  • 顺便说一句,您的意思是 250 个并发线程(或者其中一些线程已经终止)?

标签: c++ linux multithreading sockets posix


【解决方案1】:

每当你达到线程限制时——或者如前所述,由于线程数量而耗尽了虚拟进程地址空间——你就是在....做错了。更多线程无法扩展。尤其是在进行嵌入式编程时。您可以改为在线程池上处理请求。使用poll(2) 在更少的线程上处理多个连接。这是一个非常成熟的领域,图书馆(如 ACE、asio)一直在利用这种模式是有充分理由的

'thread-per-request' 模型之所以受欢迎,主要是因为它(被认为是)简单的设计。

不过,只要您在单个 逻辑 线程(有时称为 strand)上保持连接,就没有真正的区别。

另外,如果请求的处理不涉及阻塞操作,你永远不会比在单个线程上轮询和处理更好:你可以使用 bind/accept 的 'backlog' 特性让 内核 为您担心挂起的连接! (注意:这是假设一个单核 CPU,在双核 CPU 上这种处理将是最佳的,每个 CPU 一个线程)

编辑补充回复:

ulimit 显示了操作系统可以处理多少线程,对吧?如果是,ulimit 不能解决我的问题,因为我的应用同时使用了 ~10-15 个线程。

如果是这种情况,你真的应该仔细检查你是否加入了正确地分离了所有线程。还要考虑同步对象;如果您一直忘记调用相关的 pthread *_destroy 函数,即使不需要它,您也会遇到限制。这当然是资源泄漏。一些工具可能可以帮助您发现它们(想到 vlagrind/helgrind)

【讨论】:

  • @Edward:添加评论以回应 Edward 的评论
  • 谢谢。 pthread_detach 解决了我的问题。也感谢有关线程的更多信息。很有用!
【解决方案2】:

使用 ulimit -n 检查文件系统句柄的数量。如果数量太少,您可以为当前会话增加它。

您也可以编辑 /etc/security/limits.conf 并设置永久限制

【讨论】:

  • 好的。我可以在某个地方定义一些东西来创建无限数量的线程,当然,如果有空闲内存和 cpu 时间?
  • ulimit 显示操作系统可以处理多少线程,对吧?如果是,ulimit 不能解决我的问题,因为我的应用同时使用了 ~10-15 个线程。
【解决方案3】:

通常,您在 32 位系统上遇到的第一个限制是使用默认堆栈大小时虚拟地址空间不足。

尝试在创建线程时明确指定堆栈大小(小于 1 MB)或使用“ulimit -s”设置默认堆栈大小。

另请注意,您需要 pthread_detach 或 pthread_join 线程,以便释放所有资源。

【讨论】:

  • 我的客户端线程在退出之前会清除所有指针,关闭所有描述符。而且它不使用太多内存。 pthread 退出后是否清栈?
  • 当线程正确终止时,该堆栈被释放。你是分离线程(pthread_detach)还是加入(pthread_join)?
  • 别忘了您可以在创建时使用 pthread 属性设置堆栈大小 (pthread_attr_setstacksize)
猜你喜欢
  • 2019-04-24
  • 1970-01-01
  • 2011-11-14
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多