linux手册翻译——epoll_wait(2)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux手册翻译——epoll_wait(2)相关的知识,希望对你有一定的参考价值。

参考技术A


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 分钟的超时被视为无穷大

linux手册翻译——sendfile(2)

参考技术A


sendfile - transfer data between file descriptors


sendfile() 在一个文件描述符和另一个文件描述符之间复制数据。 因为这种复制是在 内核中完成 的,所以 sendfile() 比 read(2) 和 write(2) 的组合更有效,后者需要将数据传入和传出用户空间。

in_fd 是一个为读取而打开的文件描述符, out_fd 是一个为写入而打开的描述符。

如果 offset 不为NULL,则sendfile()将以其为偏移量从 in_fd 中读取数据。当 sendfile() 返回时,此变量将设置为读取的最后一个字节之后的偏移量。 如果 offset 为 NULL,则将从 in_fd 中的文件偏移量开始读取数据。

需要注意!如果指定了 offset ,那么读取 in_fd 中的数据是不会修改其打开文件自身的偏移量的。

count 是要在文件描述符之间复制的字节数。

in_fd 参数必须是支持类似 mmap(2) 等操作的文件(即它不能是套接字)。

在 2.6.33 之前的 Linux 内核中, out_fd 必须引用套接字。 从 Linux 2.6.33 开始,它可以是任何文件。 如果它是一个常规文件,则 sendfile() 适当地更改 out_fd 的文件偏移量。


如果传输成功,则返回写入 out_fd 的字节数。 请注意,成功调用 sendfile() 可能会写入比请求更少的字节; 如果有未发送的字节,调用者应该准备重试调用。 另见NOTES。
出错时,返回 -1,并设置 errno 以指示错误。


sendfile() 首次出现在 Linux 2.2 中。 从 glibc 2.1 开始就存在包含文件 <sys/sendfile.h>。


Not specified in POSIX.1-2001, nor in other standards.

Other UNIX systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs.


sendfile() 最多传输 0x7ffff000 (2,147,479,552) 个字节,返回的是实际传输的字节数。 (在 32 位和 64 位系统上都是如此。)

如果您计划使用 sendfile() 将文件发送到 TCP 套接字,但需要在文件内容之前发送一些标头数据,您会发现使用 TCP_CORK 选项很有用,在 tcp(7) 中描述,以最小化 数据包的数量并调整性能。

根据tcp(7),TCP_CORK的作用是:如果设置,则不发送部分帧。 当再次清除该选项时,将发送所有排队的部分帧。更方便的,可以在执行时send()时设置MSG_MORE标志,见 send(2)

在 Linux 2.4 及更早版本中,out_fd 也可以指普通文件; 这种可能性在 Linux 2.6.x 内核系列中消失了,但在 Linux 2.6.33 中恢复了。

最初的 Linux sendfile() 系统调用不是为了处理大文件偏移量而设计的。 因此,Linux 2.4 添加了 sendfile64(),偏移参数的类型更宽。 glibc sendfile() 包装函数透明地处理内核差异。

在 sendfile() 因 EINVAL 或 ENOSYS 失败的情况下,应用程序可以回退到 read(2)/write(2)。

如果 out_fd 引用了具有零拷贝支持的套接字或管道,则调用者必须确保 in_fd 引用的文件的传输部分保持不变,直到 out_fd 另一端的读取器消耗了传输的数据。

Linux 特定的 splice(2) 调用支持在任意文件描述符之间传输数据,前提是其中一个(或两个)是管道。

以上是关于linux手册翻译——epoll_wait(2)的主要内容,如果未能解决你的问题,请参考以下文章

linux手册翻译——timerfd_create(2)

Linux sort命令中文手册(info sort翻译)

linux中man命令的使用

Linux内核Makefile文件(翻译自内核手册)

[转帖]3. GC 算法(基础篇) - GC参考手册

linux手册翻译——iptables(8)