【问题标题】:Concurrent system calls in LinuxLinux 中的并发系统调用
【发布时间】:2016-11-14 19:24:07
【问题描述】:

这个问题很简单,我在谷歌上没有找到任何关于它的信息。对 Linux 系统进行并发调用是否安全,例如同时(可能)在多个线程上调用 socket()?具体来说,内核是否保证socket()connect() 和/或send() 的线程安全?

如果不是,为什么不呢?我真的很想了解更多关于这个主题以及为什么系统调用是或不是线程安全的。

我主要关心的是socket() 在从不同线程调用时不会返回重复或无效的文件描述符。在我的情况下,我不会同时连接或写入同一个套接字。

【问题讨论】:

  • 在这种情况下线程安全意味着什么?

标签: c++ linux multithreading concurrency system-calls


【解决方案1】:

“你会让系统崩溃吗?” 不会。

“你的线程是否会相互‘竞争’或‘竞争’,从而得到完全不可预测和不可重现的结果?肯定是的。

内核通常将资源(例如套接字......)视为由所有线程所属的进程拥有。 而且,如果某个特定调用正在“阻塞”,它可能会阻塞进程。

最后,socket 操作,例如send,实际上并没有从线程的使用中受益,因为数据包是通过 (相对较慢...)单线,一次一根,以毫秒的速度。一个简单的select() 轮询循环通常工作得很好。 “复杂性不会得到回报。”

【讨论】:

  • 谢谢。考虑到这一点,我会考虑重新设计我的应用程序。
  • 只需从 GitHub 或您选择的编程语言的贡献库中获取“现成的”服务器代码。使用它,或者直接复制它。
  • 这个答案具有误导性——特别是阻塞系统调用不会阻塞整个进程(至少在任何现代操作系统上都不会)。它只会阻塞发出调用的线程。此外,许多程序将多个线程与套接字一起使用就可以了。做对比单线程更棘手,但如果程序员知道他在做什么,这是一种完全可以接受的方法,并且它是常用的。至于与多路复用单线程方法相比是否有益,这在很大程度上取决于线程除了发送/接收之外还需要做什么。
  • “如果一个特定的调用是“阻塞的”,它可能会阻塞进程。 - 这是完全错误的。
  • 感谢指正,immibis。我已经相应地更新了回复。
【解决方案2】:

对Linux系统进行并发调用是否安全,例如 同时(可能是)在多个线程上调用 socket()?

是的,它们是线程安全的。虽然我不确定它是否符合 POSIX 标准。

具体来说,内核是否保证 socket() 的线程安全, 连接()和/或发送()?

根据THIS 链接,是的。它说锁是在内部使用的,这意味着您的send 操作将被序列化,但不是按任何特定顺序。

回答更新部分问题:

我主要担心的是 socket() 不会返回 从不同的地方调用时重复或无效的文件描述符 线程。

这里不用担心。操作系统将确保套接字的文件描述符不重复。

【讨论】:

  • “你会使系统崩溃吗?” 不会。“你的线程可能会相互‘竞争’或‘竞争’,从而得到完全不可预测的结果吗?肯定会是的。
  • 是的,有效积分。但是竞争条件只能在 STREAM 协议中观察到,UDP 是一次性的,不会因竞争发送缓冲区数据而受到影响。
  • @MikeRobinson 在这种情况下,我使用的是 TCP 套接字,并且从不同时写入同一个套接字。真的,我担心的是调用socket() 并获得重复或无效的文件描述符。只要保证不会发生,我就很高兴。
  • @RogueCSDev 不要再害怕了。调用socket 不会给你已经存在的文件描述符。
  • ... 但是您的 process 中的每个 thread 共享相同的文件描述符。而且,基本上,即使我们想到“套接字”,它也归结为 TCP/IP 数据包,硬件一次发送和接收一个。
猜你喜欢
  • 2012-06-30
  • 1970-01-01
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
  • 2012-12-30
  • 2016-05-12
  • 2016-03-02
  • 1970-01-01
相关资源
最近更新 更多