(1)关于 epoll 操作的三大系统函数: epoll_create ( … ) 、 epoll_ctl ( … ) 、 epoll_wait(…)。具体的函数原型略。这些函数完成了 epoll 对象的创建、 套接字往 epoll 红黑树中的添加、修改 与 删除 。 本文的整理的资料是, close ( fd_socket ) 后,是否需要手动把其从 epoll 红黑树里删除:
(2) 以下为搜集的答案:
++以上答案来自某心一言,以下的回答来自 c 知道 :
(3)今天用代码验证了下, close ( sockFd ) 以后,就不要再使用 epoll_ctl ( EPOLL_MOD_DEL … ) 了,会报错误,描述符找不到, epoll 对象很智能啊 :
++ 给出代码版。本代码很简单,建立套接字启用监听后,扔到 epoll 对象里,就开始测试:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <fcntl.h> //增加这俩头文件
int main( )
{ //验证被关闭的套接字是否会自动被 epoll对象剔除出红黑树
int serv_sock, epfd ; // 套接字对象与 epoll对象的描述符
struct sockaddr_in serv_adr; // 套接字的 ip地址与端口号
struct epoll_event event ; // 对应于套接字的事件
serv_sock = socket(PF_INET,SOCK_STREAM,0);
printf("创建了监听套接字,描述符为: %d\n",serv_sock);
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family = AF_INET ; // 协议
serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址
serv_adr.sin_port = htons( 80 ); // 监听端口号 80
bind( serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr) ) ;
listen(serv_sock,5);
epfd = epoll_create( 50 ); // 随便给个数
event.events = EPOLLIN; event.data.fd = serv_sock;
//int epoll_ctl(int epfd, int op, int fd, epoll_event * event);
epoll_ctl(epfd, EPOLL_CTL_ADD, serv_sock, &event);//成0败-1并设置errno
close(serv_sock); //删除套接字,那么它还在 epoll 红黑树中么?
if( ! epoll_ctl(epfd, EPOLL_CTL_MOD, serv_sock, &event) )
printf("验证发现: 被关闭的套接字仍在 epoll红黑树中\n");
else
perror("打印全局的 errno 错误信息:"); //测试发现会打印这一行
}
++ 测试结果如下:
++ 这说明,在新版本的 linux 内核里,扩充了系统函数 close(fd) 的功能,在关闭内存中的文件节点以前, close () 会发现有 epoll 对象引用了本 套接字,其会等待 epoll 的红黑树里删除了此套接字后,再关闭 套接字对应的文件节点。
这里给出 linux 0.11 里的老版本 close() 的定义,扩充此 close()函数的功能还是可以做到的:
(4)
谢谢