栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Linux select()vs ppoll()vs pselect()

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux select()vs ppoll()vs pselect()

我建议通过与

select()
vs 开始比较
poll()
。Linux还提供
pselect()
ppoll()
;和和(vs
和)的额外
const sigset_t *
参数对每个“
p变量”具有相同的作用。如果您不使用信号,那么您就没有竞争的机会,因此,基本问题实际上是关于效率和易于编程的问题。
pselect()``ppoll()``select()``poll()

至于比赛:一旦开始使用信号(无论出于何种原因),您将了解到,信号处理程序通常应设置一个类型变量,

volatilesig_atomic_t
以指示已检测到信号。造成这种情况的根本原因是,许多库调用都不是可重入的,并且可以在您处于此类例程“中间”时传递信号。例如,仅将消息打印到流样式的数据结构(例如
stdout
(C)或
cout
(C
++))会导致重新进入问题。

假设您有使用

volatile sig_atomic_tflag
变量(可能是catch)的代码,
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(...);     }

那么可能会 您调用

select()

之前
poll()
而不是之后发生中断。在这种情况下,您确实被打断了,并且变量
got_interrupted
被设置了,但是在那之后,您开始等待。您应该
got_interrupted
在开始等待之前而不是之后检查变量。

您可以尝试编写:

    while (!got_interrupted) {        ... do some work ...        if (!got_interrupted) result = select(...);     }

这会缩小“竞赛窗口”,因为现在您可以在“执行一些工作”代码时检测到中断(如果发生);但是仍然存在竞争,因为中断可能 您测试变量 后立即 发生,而
选择或轮询 之前 发生。

解决方案是使用

sigprocmask
(或在POSIX线程代码中
pthread_sigmask
)的信号阻止属性使“测试,然后等待”序列“原子”化:

sigset_t mask, omask;...while (!got_interrupted) {    ... do some work ...        sigemptyset(&mask);    sigaddset(&mask, SIGINT);    if (sigprocmask(SIG_BLOCK, &mask, &omask))        ... handle error ...    if (got_interrupted) {        sigprocmask(SIG_SETMASK, &omask, NULL);         break;    }    result = pselect(..., &omask);     sigprocmask(SIG_SETMASK, &omask, NULL);    }

(上面的代码实际上并不是那么好,它只是为了说明而不是为了效率而设计的-稍微不同地进行信号屏蔽操作,并以不同的方式放置“中断”测试会更加有效)。

但是,直到您真正开始需要捕获之前

SIGINT
,您只需要比较
select()
poll()
(并且如果您开始需要大量的描述符,则某些基于事件的东西(例如,
epoll()
其中之一)要比任何一个都更有效)。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/369285.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号