我有两次event_wait调用 线程1:来自子进程的侦听管道
struct epoll_event *ev;
struct EpollStub stub[pool->plugins.count];
...
epollfd = epoll_create1(0);
if (epollfd == -1) {
return -1;
}
ev->events = EPOLLIN;
for(int i=0;i<plugins->count;i++) {
inf = &plugins->stp[i];
stub[i].type = EREAD_STAP;
stub[i].pointer = inf;
ev->data.ptr = stub+i;
if (epoll_ctl(pool->epollfd, EPOLL_CTL_ADD, inf->fd, ev) == -1) {
close(epollfd);
return -1;
}
}
do {
n = epoll_wait(pool->epollfd, evs, EPOLL_EVENTS_MAX, -1);
for(int i=0;i<n;i++) {
ev = evs + i;
struct EpollStub *stub = (struct EpollStub *)ev->data.ptr;
if(stub->type!=EREAD_STAP) {
#ifdef __MDEBUG
printf("EREAD: Wrong event: %d\n",stub->type);
#endif
continue;
}
else {
// inf = (struct StpInfo*)ev->data.ptr;
inf = (struct StpInfo*)stub->pointer;
fd = inf->fd;
#ifdef __MDEBUG
printf("EREAD fd: %d\n",fd);
#endif
///do something here
}
....
主题2:倾听客户端套接字
struct epoll_event ev;
pool->epollfd = epoll_create1(0);
if (pool->epollfd == -1) {
return -1;
}
ev.events = EPOLLIN;
for(int i=0;i<pool->sockets.count;i++) {
struct EpollStub *stub = &pool->sockets.stub[i];
stub->type = EACCEPT_CONN;
stub->pointer = pool->sockets.fd[i];
ev.data.ptr = stub;
if (epoll_ctl(pool->epollfd, EPOLL_CTL_ADD, (int)stub->pointer, &ev) = -1) {
return -1;
}
}
...
cfd = epoll_wait(pool->epollfd, &ev, 1, -1);
if(is_working(pool,cfd)) {
struct EpollStub *stub = (struct EpollStub *)ev.data.ptr;
if(stub->type!=EACCEPT_CONN) {
#ifdef __MDEBUG
printf("EACCEPT: Wrong event: %d\n",stub->type);
#endif
}
else {
#ifdef __MDEBUG
printf("EACCEPT fd: %d\n",(int)stub->pointer);
#endif
break;
///do something here
}
}
....
kernel:opensuse-3.1.0-1.2-desktop
他们互相得到了一些事件。我让EpollStub只是因为他们得到了保姆。如果没有这个第一个事件,则返回指针第二个句柄,结果是接收描述符时的分段错误并将其用作指针。
我认为这不是正常行为。这是内核中的错误或我错在哪里?
答案 0 :(得分:1)
这是您代码中的错误。您在一些地方混淆了pool->epollfd
和epollfd
,例如:
epollfd = epoll_create1(0);
if (epollfd == -1) {
return -1;
}
ev->events = EPOLLIN;
for(int i=0;i<plugins->count;i++) {
inf = &plugins->stp[i];
stub[i].type = EREAD_STAP;
stub[i].pointer = inf;
ev->data.ptr = stub+i;
if (epoll_ctl(pool->epollfd, EPOLL_CTL_ADD, inf->fd, ev) == -1) {
close(epollfd);
return -1;
}
}
do {
n = epoll_wait(pool->epollfd, evs, EPOLL_EVENTS_MAX, -1);
您创建epollfd
,但随后修改pool->epollfd
并等待。如果您有两个不同的事件集,则需要使用两个不同的epoll fds。
epoll机制完全与线程无关。它不会将事件或集绑定到线程。任何线程都可以在集合中添加或删除描述符。任何线程都可以为任何集合获取事件。