- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
在我的应用程序中,有一个 io 线程,专用于
应用程序通过不同的线程处理数据。此外,要求规定未确认的窗口大小应为 1,即在任何时候都应该只有一个待处理的未确认消息。这意味着如果 io-thread 已经通过套接字发送了一条消息,它将不会再发送任何消息,直到它听到来自接收方的确认。应用程序的处理线程通过管道与 io-thread 通信。如果有人从 linux CLI 键入 ctrl+C,应用程序需要正常关闭。因此,鉴于这些要求,我有以下选择
我有以下问题
select() 和 poll() 之间的决定。我的应用程序只处理少于 50 个文件描述符。可以假设我选择 select 还是 poll 没有区别吗?
select() 和 pselect() 之间的决定。我阅读了 linux 文档,它说明了信号和 select() 之间的竞争条件。我没有信号方面的经验,所以有人可以更清楚地解释竞争条件和 select() 吗?是否与有人在 CLI 上按 ctrl+C 而应用程序没有停止有关?
pselect 和 ppoll() 之间的决定?关于一个与另一个的任何想法
最佳答案
我建议先比较 select()
与 poll()
。 Linux 还同时提供了pselect()
和ppoll()
;以及 pselect()
和 ppoll()
的额外 const sigset_t *
参数(对比 select()
和 poll()
) 对每个“p-variant”具有相同的效果。如果你不使用信号,你就没有竞争来防止,所以基本问题实际上是关于编程的效率和易用性。
同时这里已经有一个 stackoverflow.com 的答案:what are the differences between poll and select .
至于比赛:一旦你开始使用信号(无论出于何种原因),你将了解到,一般来说,信号处理程序应该只设置一个 volatile sig_atomic_t
类型的变量来指示信号已被检测到。根本原因是许多库调用不是 re-entrant ,并且可以在您“处于”这样的例程中时发出信号。例如,简单地将消息打印到流式数据结构,例如 stdout
(C) 或 cout
(C++) 可能会导致重入问题。
假设您有使用 volatile sig_atomic_t flag
变量的代码,可能是为了捕获 SIGINT
,就像这样(另请参见 http://pubs.opengroup.org/onlinepubs/007904975/functions/sigaction.html ):
volatile sig_atomic_t got_interrupted = 0;
void caught_signal(int unused) {
got_interrupted = 1;
}
...
struct sigaction sa;
sa.sa_handler = caught_signal;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGINT, &sa, NULL) == -1) ... handle error ...
...
现在,在您的代码主体中,您可能希望“运行直到被中断”:
while (!got_interrupted) {
... do some work ...
}
这很好,直到您开始需要进行等待某些输入/输出的调用,例如 select
或 poll
。 “等待”操作需要等待该 I/O——但它也需要等待 SIGINT
中断。如果你只是写:
while (!got_interrupted) {
... do some work ...
result = select(...); /* or result = poll(...) */
}
那么中断有可能就在您调用select()
或poll()
之前发生,而不是之后发生。在这种情况下,您确实被打断了——并且变量 got_interrupted
被设置了——但在那之后,您开始等待。您应该在开始等待之前检查 got_interrupted
变量,而不是之后。
你可以试试写:
while (!got_interrupted) {
... do some work ...
if (!got_interrupted)
result = select(...); /* or result = poll(...) */
}
这缩小了“竞赛窗口”,因为现在您将检测到在您处于“做一些工作”代码时发生的中断;但是仍然存在竞争,因为中断可能发生在您测试变量之后,但就在 select-or-poll 之前。
解决方案是使用 sigprocmask
的信号阻塞属性(或者,在 POSIX 线程代码中,pthread_sigmask
)使“测试,然后等待”序列成为“原子的” >):
sigset_t mask, omask;
...
while (!got_interrupted) {
... do some work ...
/* begin critical section, test got_interrupted atomically */
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
if (sigprocmask(SIG_BLOCK, &mask, &omask))
... handle error ...
if (got_interrupted) {
sigprocmask(SIG_SETMASK, &omask, NULL); /* restore old signal mask */
break;
}
result = pselect(..., &omask); /* or ppoll() etc */
sigprocmask(SIG_SETMASK, &omask, NULL);
/* end critical section */
}
(上面的代码实际上并不是那么好,它的结构是为了说明而不是效率——稍微不同地进行信号掩码操作,并以不同方式放置“被中断”测试会更有效)。
不过,在您真正开始需要捕获 SIGINT
之前,您只需要比较 select()
和 poll()
(如果您开始需要大量的描述符,一些基于事件的东西比如 epoll()
比任何一个都更有效。
关于c - Linux select() vs ppoll() vs pselect(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9774986/
我有一个 QThread,它从套接字读取数据并在有可用数据时发送信号(QT 信号)。阻塞读取 (2) 会很容易,但我需要能够从外部停止线程而无需等待太久。 如果我使用 pthread,我会使用 pse
逻辑 while() { block signal; pselect(); unblock signal; } 当信号被阻塞时,我可以存储发送信号的进程 ID 吗?以便我在 pselect
首先,我没有资格将此标记为关于“pselect”的问题,所以我选择了“select”。 我使用 pselect 来处理 UDP 套接字上的超时。代码如下所示: UDP_STATUS udp_socke
在服务器代码中,我想使用 pselect 等待客户端连接,并监视我创建的过程的标准输出并将其发送到客户端(如简化的远程 shell)。 我试图找到有关如何使用 pselect 的示例,但没有找到。客户
我有一个多线程服务器,它使用这些循环生成新线程: while(handle->m_run) { if (handle->m_curThreadCount m_maxThreads) {
我无法理解 pselect 的行为。基本上我做的是以下内容: 为 SIGCHILD 信号注册一个处理程序 创建两个管道 使用fork 创建一个子进程 让 child 睡5秒,然后退出 在父进程调用ps
我正在制作一个需要同时使用套接字 io 和共享内存的消息传递服务。无论输入来自何处,例程都是相同的,唯一的区别是本地消息将通过共享内存和非本地消息通过套接字传递。这两个事件都必须取消阻止同一个 pse
我在从 POSIX 套接字 (RHEL6 x86_64 C++ icpc) 读取时遇到间歇性延迟。我的代码被设计成用户可以提供一个绝对的 timespec 截止日期(相对于一个相对超时)来跨多个 re
我正在尝试使用 ptrace 监控二进制文件的系统调用。二进制文件在 pselect() 中休眠并且没有 ptrace,SIGQUIT 使其从 pselect 返回。传递给 pselect 的阻塞信号
POSIX pselect function采用信号掩码参数。在函数开始执行之前,信号掩码被“原子地”设置为当前掩码,并在函数返回时恢复。 这允许在函数执行时取消屏蔽以其他方式屏蔽的信号,并在函数返回
我正在学习如何使用 pselect。我采用了一个运行良好的示例代码并将其修改为从 main 产生的线程调用相同的代码但它不起作用(pselect 永远被阻止) #include #include
我有一个正在处理的应用程序,它需要几个辅助线程,每个辅助线程将负责多个文件句柄(至少 1 个,最多 10 个)。文件句柄不在线程之间共享,因此在选择查看准备好读取/写入的内容时,我不必担心一个辅助线程
以下面的代码片段为例,套接字的创建、新套接字的监听和接受工作正常。非阻塞模式也可以工作,但是 pselect(甚至替换为 select)无法识别 FDset 上就绪的任何 IO 请求。所以返回值总是0
我正在尝试为我的事件驱动应用程序添加一个信号处理程序以进行适当的清理。 我的 SIGINT 信号处理程序仅更改全局标志变量的值,然后在主循环中对其进行检查。为了避免比赛,信号一直被封锁,除了在 pse
是 POSIX pselect 在 Perl 中可用吗? CPAN 模块也很好。 最佳答案 据我所知(2010 年 2 月),POSIX 模块和任何其他模块都没有提供对 pselect() 的支持。功
我有一个服务器将消息接收到套接字中,并且对于接收到的每条消息,执行一个 fork exec。这部分似乎工作正常。 但我需要在非阻塞模式下执行此操作,因此我创建了一个处理程序来使用 waitpid()
我正在尝试使用 pselect 实现一个基本的事件循环,所以我屏蔽了一些信号,保存了信号掩码并将其与 pselect 一起使用,这样信号就会仅在该通话期间交付。 如果信号是在 pselect 调用之外
在我的应用程序中,有一个 io 线程,专用于 在自定义协议(protocol)中包装从应用程序接收的数据 通过tcp/ip发送数据+自定义协议(protocol)包 通过tcp/ip接收数据+自定义协
select() and pselect()系统调用修改它们的参数('fd_set *' 参数),因此输入值告诉系统要检查哪些文件描述符,返回值告诉程序员哪些文件描述符当前可用。 如果您要为同一组文件
我是一名优秀的程序员,十分优秀!