int epfd = epoll_create(MAX_EVENTS); 和 epoll_create1 有什么区别
时间: 2024-03-23 11:43:30 浏览: 197
在Linux 2.6.8之后,epoll_create()系统调用已被epoll_create1()系统调用替代。它们之间的主要区别在于epoll_create1()允许指定标志来控制epoll实例的行为。
epoll_create1()的第一个参数与epoll_create()相同,表示epoll实例的大小(不再是最大事件数,而是epoll实例中的文件描述符数),第二个参数flags可以是以下值之一:
- EPOLL_CLOEXEC:在执行exec()函数时自动关闭epoll实例。
- EPOLL_NONBLOCK:将epoll实例设置为非阻塞模式。
例如,下面是使用epoll_create1()创建epoll实例的示例代码:
```
int epfd = epoll_create1(EPOLL_CLOEXEC);
```
这将创建一个epoll实例,并在执行exec()函数时自动关闭它。
总之,epoll_create1()是epoll_create()的增强版,可以更好地控制epoll实例的行为。
相关问题
请使用epoll将下面的程序改为非阻塞 接收 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <linux/netlink.h> #include <sys/socket.h> #define UEVENT_BUFFER_SIZE 2048 int main(int argc, char **argv) { int fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (fd < 0) { perror("Failed to create socket"); return EXIT_FAILURE; } struct sockaddr_nl addr; memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = NETLINK_KOBJECT_UEVENT; if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("Failed to bind socket"); close(fd); return EXIT_FAILURE; } char buf[UEVENT_BUFFER_SIZE]; while (1) { ssize_t n = recv(fd, buf, sizeof(buf), 0); if (n < 0) { perror("Failed to receive data"); close(fd); return EXIT_FAILURE; } char *p = buf; while (p < buf + n) { printf("%s\n", p); p += strlen(p) + 1; } } close(fd); return EXIT_SUCCESS; }
以下是使用epoll将程序改为非阻塞接收的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#define UEVENT_BUFFER_SIZE 2048
#define MAX_EVENTS 10
int main(int argc, char **argv)
{
int fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if (fd < 0) {
perror("Failed to create socket");
return EXIT_FAILURE;
}
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_groups = NETLINK_KOBJECT_UEVENT;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("Failed to bind socket");
close(fd);
return EXIT_FAILURE;
}
// 创建 epoll 实例
int epfd = epoll_create1(0);
if (epfd < 0) {
perror("Failed to create epoll instance");
close(fd);
return EXIT_FAILURE;
}
// 将 fd 添加到 epoll 实例
struct epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET; // 设置为边沿触发模式
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) < 0) {
perror("Failed to add fd to epoll");
close(epfd);
close(fd);
return EXIT_FAILURE;
}
char buf[UEVENT_BUFFER_SIZE];
while (1) {
struct epoll_event events[MAX_EVENTS];
int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
if (n < 0) {
perror("Failed to wait for events");
break;
}
for (int i = 0; i < n; i++) {
if (events[i].events & EPOLLIN) {
ssize_t n = recv(fd, buf, sizeof(buf), 0);
if (n < 0) {
perror("Failed to receive data");
break;
}
char *p = buf;
while (p < buf + n) {
printf("%s\n", p);
p += strlen(p) + 1;
}
}
}
}
close(epfd);
close(fd);
return EXIT_SUCCESS;
}
```
主要的改动如下:
1. 创建了一个 epoll 实例,并将 socket fd 添加到 epoll 实例中;
2. 将 while 循环改为 epoll_wait 调用,用于等待事件;
3. 在接收到 EPOLLIN 事件时,调用 recv 函数接收数据。
注意,我们将 epoll 实例设置为边沿触发模式(EPOLLET),这意味着一旦有数据到达,就会触发一次 EPOLLIN 事件,而不是像水平触发模式(EPOLLIN)那样在数据到达时持续触发 EPOLLIN 事件。这样可以避免 epoll_wait 函数一直返回可读事件,从而提高程序的效率。
socket如何注册到epoll_wait的
Socket在Linux系统中通常通过Epoll机制进行事件驱动编程,Epoll是一种高效的选择器,它允许一个进程对多个文件描述符(包括socket)进行监控。为了将socket注册到`epoll_wait`,你需要按照以下步骤操作:
1. **创建Epoll实例**:
首先,需要包含头文件`#include <sys/epoll.h>`,并初始化一个epoll结构体变量`epfd`,例如:`int epfd = epoll_create(1);`这会创建一个 Epoll 实例。
2. **注册Socket**:
对于每个你要监控的socket,调用`epoll_ctl(epfd, EPOLL_CTL_ADD, file descriptor, &event)`。这里的`file descriptor`是socket对应的整数值,`event`是一个包含了事件标志的Epoll_event结构体,比如EPOLLIN(表示读就绪)或EPOLLOUT(表示写就绪)。
```c
struct epoll_event event;
event.events = EPOLLIN; // 或者其他你关心的事件
event.data.fd = your_socket_fd; // 替换为实际的socket描述符
epoll_ctl(epfd, EPOLL_CTL_ADD, event.data.fd, &event);
```
3. **轮询等待事件**:
使用`epoll_wait(epfd, events, max_events, timeout)`函数阻塞等待事件。`events`数组接收事件信息,`max_events`是你想要处理的最大事件数,`timeout`是超时时间(0表示无限等待,-1表示立即返回)。
4. **检查并处理事件**:
当`epoll_wait`返回时,你可以遍历`events`数组,检查每个socket的状态变化,并采取相应的操作。
5. **注销Socket**:
当不再需要监视某个socket时,可以调用`epoll_ctl(epfd, EPOLL_CTL_DEL, file descriptor, NULL)`从Epoll集合中删除。
```c
struct epoll_event del_event;
del_event.events = 0;
del_event.data.fd = removed_socket_fd;
epoll_ctl(epfd, EPOLL_CTL_DEL, del_event.data.fd, NULL);
```
阅读全文