【发布时间】:2013-06-04 04:31:53
【问题描述】:
情况:
- 多个进程共享同一个文件描述符表。
- 每个进程都监听自己的 epoll 实例。
- 所有套接字和涉及它们的调用都是非阻塞的。
- 在这些进程中,只有进程 A 将侦听套接字添加到其 epoll 实例中。
- 进程 A 知道所有其他进程的 epoll 的 fd。
- 当新套接字(即新连接)到达时,进程 A 将其添加到其他进程之一的 epoll 实例中...
...像这样:
int new_sfd;
while ((new_sfd = accept4(listening_fd, NULL, NULL, SOCK_NONBLOCK)) != -1) {
if (epoll_ctl(other_epoll_fds[new_sfd % PROCESS_C], EPOLL_CTL_ADD, new_sfd,
&(struct epoll_event){
.data = {.fd = new_sfd},
.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET
}) == -1) {
perror("Failed to add a new socket to an epoll instance");
close(new_sfd);
}
}
if (errno != EAGAIN) {
perror("Failed to accept one or more incoming connections");
}
这似乎有效(即在此阶段没有发生错误)。当一个连接进入进程 A 时,它被添加到进程 B 的 epoll 中,之后进程 B 得到一个设置了 EPOLLIN 标志的事件,正如预期的那样。然后进程B通过读取接收到的epoll_event结构的data.fd成员获取新socket的fd,并在该fd上尝试recv()。
这里出乎意料地出错了。 recv() 返回 -1 并出现以下错误:Socket operation on non-socket。
什么给了?通过在各处插入大量调试printf() 语句,我已经彻底验证了进程A 中accept4() 返回的fd 值实际上与我作为第一个参数传递给recv() 中的fd 值相同进程 B(同样,所有进程共享同一个文件描述符表),所以我无法理解这一点。帮助?! D:
【问题讨论】:
标签: c linux sockets file-descriptor epoll