linux手册翻译——epoll_wait(2)

linux手册翻译——epoll_wait(2),第1张

epoll_wait, epoll_pwait, epoll_pwait2 - 在epoll fd上等待I/O事件

events 指向了事件缓冲区,每当interest list中fd触发事件加入到ready list后,会将其返回到事件缓冲区中。最大返回 maxevents 个,因此 maxevent s至少大于0。返回的event顺序写入缓冲区。 timeout 参数指定epoll_wait将阻塞的毫秒数。

epoll_wait()将会一直阻塞直到:fd产生事件 / 被信号处理函数打断 / 超时。

时间测量将使用CLOCK_MONOTONIC (系统启动后到现在的时间,记录的是tick的总次数) 时钟,超时时间将向上舍入到系统时钟粒度,内核调度延迟可能让阻塞时间稍微超出。指定为-1时将无限期阻塞,指定为0时若没有可用事件则立即返回。

返回的epoll_event中,data字段与使用event_ctl(2)(EPOLL_CTL_ADD,EPOLL_CTL_MOD)传入的data一致。 (所以一般来说用fd足矣) ,而events字段是此fd触发的事件。

与epoll_wait自比,后者允许应用程序安全的等待(在调用epoll_wait(),设置自定义的信号掩码,并在epoll_wait()结束后恢复),直到文件描述等就绪或信号被捕获。

等价于:

sigmask指定为NULL时,epoll _pwait与epoll_wait相同。epoll_pwait2与epoll_pwait除timeout参数外完全相同,它指定timespec结构来执行纳秒级的等待。设为NULL时将一直等。

错误将返回-1,并设定errno;

超时将返回0

成功将返回触发I0事件的fd个数。

epoll_wait() 在 2.6 版中被添加到内核中。 从版本 2.3.2 开始,glibc 中提供了库支持。

epoll_pwait() 在内核 2.6.19 中被添加到 Linux。 从版本 2.6 开始,glibc 中提供了库支持。

epoll_pwait2() 在内核 5.11 中被添加到 Linux。

epoll_wait(), epoll_pwait(), and epoll_pwait2() are Linux-specific.

虽然一个线程在调用 epoll_wait() 时被阻塞,但另一个线程可能会向等待的 epoll 实例添加文件描述符。 如果新的文件描述符准备好,它将导致 epoll_wait() 调用解除阻塞。

如果在调用 epoll_wait() 时有超过 maxevents 个文件描述符准备就绪,那么连续的 epoll_wait() 调用将 循环遍历 准备好的文件描述符集。 此行为有助于避免饥饿情况,即进程未能注意到其他文件描述符已准备就绪,因为它专注于一组已知已准备就绪的文件描述符。循环遍历的意义就在于避免只访问固定位置的事件。

请注意,可以在 interest-list 当前为空的 epoll 实例上调用 epoll_wait() (或者其interest-list因为文件描述符被关闭或从另一个线程中的兴趣中删除而变为空)。 该调用将阻塞,直到在另一个线程中将某个文件描述符添加到interest-list并且该文件描述符准备就绪。

C library/kernel differences

原始的 epoll_pwait() 和 epoll_pwait2() 系统调用有第六个参数 size_t sigsetsize,它指定了 sigmask 参数的字节大小。 glibc epoll_pwait() 包装函数将此参数指定为固定值(等于 sizeof(sigset_t))。

在 2.6.37 之前的内核中,大于大约 LONG_MAX / HZ 毫秒的超时值被视为 -1(即无穷大)。 因此,例如,在 sizeof(long) 为 4 且内核 HZ 值为 1000 的系统上,这意味着大于 35.79 分钟的超时被视为无穷大

ssh 和telnet 差不多, 都是远程登录的客户端, 只不过ssh更安全(加密方式), telnet是明文传输.ssh IP地址ssh 域名具体可以查看man ssh或者ssh --help

一个方法是:信号+子进程的方法...显得比较繁琐...

定义一个全局变量,作为标志位

fork,让子进程去执行系统调用...

然后父进程调用alarm,设置周期为20秒,这样每隔20秒会收到一个SIGALRM;

然后注册SIGALRM和SIGCHILD这两个信号的处理函数,可以让其中一个信号处理函数去修改全局变量..(子进程返回时候父进程会收到一个SIGCHILD信号)

再然后,调用sigsuspend让父进程休眠,设置好信号掩码,保证两个信号可以唤醒父进程--SIGALRM和SIGCHILD。

然后就是你父进程被某个信号唤醒了...此时就判断是怎么被唤醒(用刚才那个全局变量判断)...要是SIGALRM,就说明超时了.要是SIGCHILD就说明没超时...后面就是你自己的事情了.两种情况分别处理呗..

当然,另外一种简单的方法(比较耗费CPU)...还是需要子进程...

先fork,然后调用waitpid,设置为立即返回,这样可以立刻判断子进程的状态,然后若时间没超出你的要求,就继续waitpid,直到时间超出20秒或者子进程在时限之前返回...这样轮询显然非常浪费CPU...(如何判断可以

man

waitpid)

别的方法...我也想不出来了...


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/6225415.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-18
下一篇2023-03-18

发表评论

登录后才能评论

评论列表(0条)

    保存