gpt4 book ai didi

c - Kqueue 返回 EVFILT_READ 和 EVFILT_WRITE 但我安装了单独的 (ident,filt) 对

转载 作者:太空狗 更新时间:2023-10-29 15:16:35 26 4
gpt4 key购买 nike

我遇到了一个问题,我不确定这是 kqueue 的预期行为还是我做错了什么。

我需要使用 kqueue 为单个套接字文件描述符安装单独的事件。单独的事件是 (sockfd,EVFILT_READ) 和 (sockfd,EVFILT_WRITE)。然而,当我稍后从 kqueue 中提取事件时,我从 kqueue 中获得了两个事件,但这两个事件都包含 (event.filter & EVFILT_READ) 和 (event.filter & EVFILT_WRITE)。

我需要将它们分开,否则我不知道哪个事件实际上已准备就绪,读取或写入?

下面是我整理的一些示例代码,用于说明该问题。请记住,这只是测试代码,用于弄清楚为什么我在每个事件中都获得两个过滤器标志。

int main(int argc, char ** argv) {
//listening_sockfd = setup listening socket

//setup kqueue and vars
int kq = kqueue();
int res = 0;
int bufres = 0;
struct timespec ts = {0};
struct timespec * tsp = &ts;
struct kevent ke2[2];

//install read for listening socket
struct kevent ke1;
bzero(&ke1,sizeof(ke1));
ke1.ident = listening_sockfd;
ke1.flags = EV_ADD;
ke1.filter = EVFILT_READ;
res = kevent(kq,&ke1,1,NULL,0,tsp);

while(1) {
new_client:

//wait for a client to connect
res = kevent(kq,NULL,0,&ke1,1,NULL);
if(res < 0) printf("%s\n", strerror(errno));

if(res > 0) {
//accept the client
int clientfd = accept(skinfo.sockfd,NULL,NULL);

//install read events for client
bzero(&ke1,sizeof(ke1));
ke1.ident = clientfd;
ke1.flags = EV_ADD;
ke1.filter = EVFILT_READ;
res = kevent(kq,&ke1,1,NULL,0,tsp);
if(res < 0) printf("%s\n",strerror(errno));

while(1) {

//wait for readable content from the client
bzero(&ke1,sizeof(ke1));
res = kevent(kq,NULL,0,&ke1,1,NULL);
if(res < 0) printf("%s\n",strerror(errno));

if(res > 0) {

//check for client disconnect
if(ke1.flags & EV_EOF) {
close(clientfd);
goto new_client;
}

//now install write events for client
bzero(&ke1,sizeof(ke1));
ke1.ident = clientfd;
ke1.flags = EV_ADD;
ke1.filter = EVFILT_WRITE;
res = kevent(kq,&ke1,1,NULL,0,tsp);
if(res < 0) printf("%s\n",strerror(errno));

//now wait for it to be writable - this will return
//immediately because the socket is writable.
res = kevent(kq,NULL,0,ke2,2,NULL);
if(res < 0) printf("%s\n",strerror(errno));

if(res >= 0) {
char buf[128];
printf("res: %i\n",res);

//we have two events from kqueue because I installed
//two (ident,filter) pairs.
int i = 0;
for(i; i<2; i++) {
printf("ident: %i\n",ke2[i].ident);
printf("filter[%i] %lu\n",i,ke2[i].filter);
printf("data: %lu\n",ke2[i].data);

//QUESTION: Why does EVFILT_READ && EVFILT_WRITE come
//back in the same event when I installed two seperate
//(ident,filter) pairs?
if(ke2[i].filter & EVFILT_READ) printf("EVFILT_READ\n");
if(ke2[i].filter & EVFILT_WRITE) printf("EVFILT_WRITE\n");

if(ke2[i].filter & EVFILT_READ) {
printf("readable!\n");
bufres = read(clientfd,buf,128);
}

if(ke2[i].filter & EVFILT_WRITE) {
printf("writable\n");

//shut off write events to stop infinite loop
//because the socket is writable
bzero(&ke1,sizeof(ke1));
ke1.ident = clientfd;
ke1.flags = EV_DELETE;
ke1.filter = EVFILT_WRITE;
res = kevent(kq,&ke1,1,NULL,0,tsp);

write(clientfd,buf,bufres);
}
}
}
}
}
}
}
}

我一直没弄明白。当我安装单独的事件时,为什么每个 kqueue 事件都包含 EVFILT_READ 和 EVFILT_WRITE?

这对我造成的真正问题是,因为这些事件总是报告 EVFILT_READ,它有代码的副作用,总是认为有可用的读取,但实际上没有,所以调用 read() 将是失败并产生其他后果。请注意,这段代码没有显示这些后果,这只是我写的问题的一个示例,所以我弄清楚了这一点并继续我的真实代码。

有什么想法吗?

PS 这是 printf 的输出:

res: 2
ident: 5
filter[0] 4294967295
data: 5
EVFILT_READ
EVFILT_WRITE
readable!
writable
ident: 5
filter[1] 4294967294
data: 146988
EVFILT_READ
EVFILT_WRITE
readable!
writable

最佳答案

啊!我想我明白了。 kqueue 文档没有说明的是 event.filter 不包含位标志。所以我需要使用 event.filter == EVFILT_READ、event.filter == EVFILT_WRITE 检查读/写。

关于c - Kqueue 返回 EVFILT_READ 和 EVFILT_WRITE 但我安装了单独的 (ident,filt) 对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12165176/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com