- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
请考虑以下程序:
#define _GNU_SOURCE
#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int verify(int result, const char *msg) {
if( result>=0 )
return result;
perror(msg);
abort();
return -1;
}
void writepipe( int fd, int num_bytes, const char *msg ) {
unsigned char buffer[num_bytes];
ssize_t num_written = verify( write(fd, buffer, num_bytes), msg );
assert( num_written==num_bytes );
}
void readpipe( int fd, int num_bytes, const char *msg ) {
unsigned char buffer[num_bytes];
ssize_t num_read = verify( read(fd, buffer, num_bytes), msg );
assert( num_read==num_bytes );
}
int main() {
int pipefds[2];
verify( pipe2(pipefds, O_NONBLOCK), "pipe creation failed" );
int epollfd = verify(epoll_create1(0), "epoll creation failed");
struct epoll_event evt;
evt.events = EPOLLIN|EPOLLET;
evt.data.u64 = 17;
verify( epoll_ctl( epollfd, EPOLL_CTL_ADD, pipefds[0], &evt ), "epoll_add failed" );
int num_events = verify( epoll_wait(epollfd, &evt, 1, 0), "epoll_wait failed" );
assert(num_events == 0);
writepipe( pipefds[1], 12, "initial filling of pipe" );
num_events = verify( epoll_wait(epollfd, &evt, 1, 0), "epoll_wait failed" );
assert(num_events == 1);
assert(evt.data.u64 == 17);
num_events = verify( epoll_wait(epollfd, &evt, 1, 0), "epoll_wait failed" );
assert(num_events == 0);
readpipe( pipefds[0], 12, "clean the data" );
num_events = verify( epoll_wait(epollfd, &evt, 1, 0), "epoll_wait failed" );
assert(num_events == 0);
writepipe( pipefds[1], 3, "write no trigger" );
num_events = verify( epoll_wait(epollfd, &evt, 1, 0), "epoll_wait on unarmed fd" );
assert(num_events == 0);
return 0;
}
最后一个断言失败。
因为我们从来没有从 epoll 中读取 EPOLLET
,所以我期望最后一个 epoll_wait
返回 0。相反,我得到了 1。
这是为什么?
来自 Ubuntu 16.10 的内核 4.13.0-39-generic。
最佳答案
迟到的答案,但可能对其他人仍有帮助。
你假设在你最后的 epoll_wait 调用中 fd 是未武装的。不是这种情况。如果你真的想让它处于非武装状态,你可以使用 EPOLLONESHOT。在它触发一次之后,你必须为 epoll 重新准备它。您可能还假设第二次写入不会导致触发 epoll。这个假设也是错误的。 EPOLLET 只保证只要 FD 上没有变化,EPOLLET 就不会再次被触发。管道上的写入会触发更改,因此会触发 epoll(不一定是人们期望发生的事情)。
The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored file descriptor.
来源:http://man7.org/linux/man-pages/man7/epoll.7.html
我真的不知道你说的“我们从来没有读过一个 EPOLLET”是什么意思,你是说 EAGAIN 表示所有数据都已被读取吗?这实际上与您的问题无关。您完全清空管道。所以下一次读取会导致 EAGAIN,但这不会改变上面提到的行为。即使不读取数据,第二次写入也会触发 epoll。检查 EAGAIN 只是为了确保在文件描述符没有变化的情况下我们完全读取所有数据。
关于linux - EPOLLET 行为不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50278921/
请考虑以下程序: #define _GNU_SOURCE #include #include #include #include #include #include #include i
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 1 年前。 Improve
我在边缘触发模式下使用epoll。为了避免饥饿,代码从一个套接字一次读取 MAX_FREAD_LENGTH 字节。随后组装片段直至 EOL 发生。我注意到当 MAX_FREAD_LENGTH 很小时,
进程 B 在管道上进行 epolls (EPOLLIN|EPOLLET)。 进程 A 在管道中写入 1KiB。 进程 B 醒来。 进程 B 从管道中读取 1KiB。 进程 A 在管道中写入 1KiB。
带有 EPOLLOUT 的 epoll TCP | EPOLLET只获取一次事件,即使我在获取第一个事件后发送数据也会超时。 而在UDP中,epoll在发送新数据后不断获取EPOLLOUT事件。 你能
写入器程序使用固定缓冲区的多次写入发送几 MB(几乎没有延迟)。处理程序在 EPOLLOUT | 中注册。 EPOLLET 标志。 MTU=16KB,写入缓冲区 = 4KB 或更多。 write(..
我在边缘触发模式下使用 linux epoll。 每次有新连接传入时,我都会使用 EPOLLIN|EPOLLOUT|EPOLLET 标志将文件描述符添加到 epoll。我的第一个问题是:在 epoll
人 epoll: The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:
epoll 联机帮助页说如果没有完成读取,用 EPOLLET(edge triggered) 注册的 fd 不应该通知两次 EPOLLIN。 因此,在 EPOLLIN 之后,您需要在 epoll_wa
是否可以在一次性级触发模式下使用epoll? 当我搜索时,我找不到任何关于它的信息;好像大家都用边沿触发的方式。 最佳答案 When the EPOLLONESHOT flag is selected
我是一名优秀的程序员,十分优秀!