epoll用法(转载)

### 使用方法 #### 创建 epoll 实例 在 Linux 中,使用 `epoll` 的第一步是创建一个 epoll 文件描述符。这可以通过调用 `epoll_create1()` 函数来完成。此函数返回一个文件描述符,用于后续的 epoll 操作。 ```c int epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create1"); exit(EXIT_FAILURE); } ``` 这段代码展示了如何创建一个 epoll 实例[^3]。 #### 添加文件描述符到 epoll 实例 一旦有了 epoll 文件描述符,下一步就是将需要监视的文件描述符添加进去。这通过 `epoll_ctl()` 函数实现,可以指定要监视的事件类型,如读就绪、写就绪等。 ```c struct epoll_event event; event.events = EPOLLIN; // 监视读事件 event.data.fd = listen_sock; // 要监视的文件描述符 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &event) == -1) { perror("epoll_ctl: listen_sock"); exit(EXIT_FAILURE); } ``` 以上代码片段演示了如何将一个监听套接字添加到 epoll 实例中[^2]。 #### 等待事件发生 接下来,程序需要等待在注册的文件描述符上发生的事件。这通过调用 `epoll_wait()` 函数完成,该函数会阻塞直到有事件发生或者超时。 ```c #define MAX_EVENTS 10 struct epoll_event events[MAX_EVENTS]; int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_wait"); exit(EXIT_FAILURE); } ``` 此代码段展示了如何等待事件的发生。 #### 处理事件 当 `epoll_wait()` 返回时,它会返回一个包含所有已触发事件的数组。应用程序需要遍历这个数组并处理每个事件。 ```c for (int i = 0; i < nfds; ++i) { if (events[i].data.fd == listen_sock) { // 处理新的连接请求 } else { // 处理数据读取或写入 } } ``` 上述代码提供了一个处理事件的基本框架[^2]。 #### 删除文件描述符 如果某个文件描述符不再需要被监视,应该从 epoll 实例中移除。同样使用 `epoll_ctl()` 函数,但这次传递 `EPOLL_CTL_DEL` 标志。 ```c if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1) { perror("epoll_ctl: DEL"); exit(EXIT_FAILURE); } ``` 此代码示例说明了如何从 epoll 实例中删除一个文件描述符[^2]。 ### 示例代码 下面是一个简单的 TCP 服务器示例,展示了如何使用 epoll 来处理多个客户端连接。 ```c #include <sys/epoll.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define PORT 8080 #define MAX_EVENTS 10 int main(void) { int listen_sock, conn_sock, epoll_fd; struct sockaddr_in serv_addr, cli_addr; socklen_t cli_len = sizeof(cli_addr); struct epoll_event event, events[MAX_EVENTS]; listen_sock = socket(AF_INET, SOCK_STREAM, 0); if (listen_sock == -1) { perror("socket"); exit(EXIT_FAILURE); } memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(PORT); if (bind(listen_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { perror("bind"); close(listen_sock); exit(EXIT_FAILURE); } if (listen(listen_sock, SOMAXCONN) == -1) { perror("listen"); close(listen_sock); exit(EXIT_FAILURE); } epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create1"); close(listen_sock); exit(EXIT_FAILURE); } event.events = EPOLLIN; event.data.fd = listen_sock; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &event) == -1) { perror("epoll_ctl: listen_sock"); close(listen_sock); close(epoll_fd); exit(EXIT_FAILURE); } while (1) { int n, i; n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); for (i = 0; i < n; i++) { if (events[i].data.fd == listen_sock) { conn_sock = accept(listen_sock, (struct sockaddr *)&cli_addr, &cli_len); if (conn_sock == -1) { perror("accept"); continue; } event.events = EPOLLIN | EPOLLET; event.data.fd = conn_sock; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_sock, &event) == -1) { perror("epoll_ctl: conn_sock"); close(conn_sock); } } else { char buf[1024]; int count = read(events[i].data.fd, buf, sizeof(buf)); if (count == -1) { perror("read"); close(events[i].data.fd); continue; } else if (count == 0) { close(events[i].data.fd); continue; } write(events[i].data.fd, buf, count); } } } close(listen_sock); close(epoll_fd); return 0; } ``` 此代码展示了一个基于 epoll 的简单 TCP 服务器,能够处理多个客户端连接[^1]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值