Linux Epool 使用学习笔记
来源:互联网 发布:渲染软件哪个好 编辑:程序博客网 时间:2024/05/19 00:38
头文件
#include <sys/epool.h>
接口和结构体
/* Creates an epoll instance. Returns an fd for the new instance. The "size" parameter is a hint specifying the number of file descriptors to be associated with the new instance. The fd returned by epoll_create() should be closed with close(). *//*创建一个epool实例。为这个实例返回一个文件描述符。size参数是这个实例所关联的文件描述符个数。返回的文件描述符应该被close接口关闭。*/extern int epoll_create (int __size) __THROW;/* Same as epoll_create but with an FLAGS parameter. The unused SIZE parameter has been dropped. *//*和epool_create一样但是带着FLAGS参数。遗弃了size参数。*/extern int epoll_create1 (int __flags) __THROW;/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */#define EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface. */#define EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure. *//* Manipulate an epoll instance "epfd". Returns 0 in case of success, -1 in case of error ( the "errno" variable will contain the specific error code ) The "op" parameter is one of the EPOLL_CTL_* constants defined above. The "fd" parameter is the target of the operation. The "event" parameter describes which events the caller is interested in and any associated user data. *//*管理epfd代表的epool实例。如果成功返回0, 出错返回-1(出错码写入errno)。op参数是上面定义的EPOLL_CTL_*中的一个。event参数包含调用者关心的的事件和对应的数据(触发类型,fd)*/extern int epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) __THROW;/* Wait for events on an epoll instance "epfd". Returns the number of triggered events returned in "events" buffer. Or -1 in case of error with the "errno" variable set to the specific error code. The "events" parameter is a buffer that will contain triggered events. The "maxevents" is the maximum number of events to be returned ( usually size of "events" ). The "timeout" parameter specifies the maximum wait time in milliseconds (-1 == infinite). This function is a cancellation point and therefore not marked with __THROW. *//*等待发生在epfd表示的epool实例上的事件。返回值是在events参数中返回的event缓存的大小。0或者-1代表出错,出错码保存在errno中。events参数指向包含触发数据的缓存。maxevents表示返回缓存的最大数目。timeout参数指定最大等待时间(-1表示永久)。*/extern int epoll_wait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout);
EPOLL_EVENTS
enum EPOLL_EVENTS { EPOLLIN = 0x001,#define EPOLLIN EPOLLIN EPOLLPRI = 0x002,#define EPOLLPRI EPOLLPRI EPOLLOUT = 0x004,#define EPOLLOUT EPOLLOUT EPOLLRDNORM = 0x040,#define EPOLLRDNORM EPOLLRDNORM EPOLLRDBAND = 0x080,#define EPOLLRDBAND EPOLLRDBAND EPOLLWRNORM = 0x100,#define EPOLLWRNORM EPOLLWRNORM EPOLLWRBAND = 0x200,#define EPOLLWRBAND EPOLLWRBAND EPOLLMSG = 0x400,#define EPOLLMSG EPOLLMSG EPOLLERR = 0x008,#define EPOLLERR EPOLLERR EPOLLHUP = 0x010,#define EPOLLHUP EPOLLHUP EPOLLRDHUP = 0x2000,#define EPOLLRDHUP EPOLLRDHUP EPOLLWAKEUP = 1u << 29,#define EPOLLWAKEUP EPOLLWAKEUP EPOLLONESHOT = 1u << 30,#define EPOLLONESHOT EPOLLONESHOT EPOLLET = 1u << 31#define EPOLLET EPOLLET };
epoll_event 结构体
typedef union epoll_data{ void *ptr; int fd; uint32_t u32; uint64_t u64;} epoll_data_t;struct epoll_event{ uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */} ;
实例代码
来自 :
http://blog.csdn.net/xiajun07061225/article/details/9250579
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <sys/socket.h>#include <netdb.h>#include <fcntl.h>#include <sys/epoll.h>#include <string.h>#define MAXEVENTS 64//函数://功能:创建和绑定一个TCP socket//参数:端口//返回值:创建的socket static intcreate_and_bind (char *port){ struct addrinfo hints; struct addrinfo *result, *rp; int s, sfd; memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ hints.ai_flags = AI_PASSIVE; /* All interfaces */ s = getaddrinfo (NULL, port, &hints, &result); if (s != 0) { fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s)); return -1; } for (rp = result; rp != NULL; rp = rp->ai_next) { sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sfd == -1) continue; s = bind (sfd, rp->ai_addr, rp->ai_addrlen); if (s == 0) { /* We managed to bind successfully! */ break; } close (sfd); } if (rp == NULL) { fprintf (stderr, "Could not bind\n"); return -1; } freeaddrinfo (result); return sfd;}//函数//功能:设置socket为非阻塞的 static intmake_socket_non_blocking (int sfd){ int flags, s; //得到文件状态标志 flags = fcntl (sfd, F_GETFL, 0); if (flags == -1) { perror ("fcntl"); return -1; } //设置文件状态标志 flags |= O_NONBLOCK; s = fcntl (sfd, F_SETFL, flags); if (s == -1) { perror ("fcntl"); return -1; } return 0;}//端口由参数argv[1]指定 intmain (int argc, char *argv[]){ int sfd, s; int efd; struct epoll_event event; struct epoll_event *events; if (argc != 2) { fprintf (stderr, "Usage: %s [port]\n", argv[0]); exit (EXIT_FAILURE); } sfd = create_and_bind (argv[1]); if (sfd == -1) abort (); s = make_socket_non_blocking (sfd); if (s == -1) abort (); s = listen (sfd, SOMAXCONN); if (s == -1) { perror ("listen"); abort (); } //除了参数size被忽略外,此函数和epoll_create完全相同 efd = epoll_create1 (0); if (efd == -1) { perror ("epoll_create"); abort (); } event.data.fd = sfd; event.events = EPOLLIN | EPOLLET;//读入,边缘触发方式 s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event); if (s == -1) { perror ("epoll_ctl"); abort (); } /* Buffer where events are returned */ events = calloc (MAXEVENTS, sizeof event); /* The event loop */ while (1) { int n, i; n = epoll_wait (efd, events, MAXEVENTS, -1); for (i = 0; i < n; i++) { if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /* An error has occured on this fd, or the socket is not ready for reading (why were we notified then?) */ fprintf (stderr, "epoll error\n"); close (events[i].data.fd); continue; } else if (sfd == events[i].data.fd) { /* We have a notification on the listening socket, which means one or more incoming connections. */ while (1) { struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof in_addr; infd = accept (sfd, &in_addr, &in_len); if (infd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* We have processed all incoming connections. */ break; } else { perror ("accept"); break; } } //将地址转化为主机名或者服务名 s = getnameinfo (&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV);//flag参数:以数字名返回 //主机地址和服务地址 if (s == 0) { printf("Accepted connection on descriptor %d " "(host=%s, port=%s)\n", infd, hbuf, sbuf); } /* Make the incoming socket non-blocking and add it to the list of fds to monitor. */ s = make_socket_non_blocking (infd); if (s == -1) abort (); event.data.fd = infd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); if (s == -1) { perror ("epoll_ctl"); abort (); } } continue; } else { /* We have data on the fd waiting to be read. Read and display it. We must read whatever data is available completely, as we are running in edge-triggered mode and won't get a notification again for the same data. */ int done = 0; while (1) { ssize_t count; char buf[512]; count = read (events[i].data.fd, buf, sizeof(buf)); if (count == -1) { /* If errno == EAGAIN, that means we have read all data. So go back to the main loop. */ if (errno != EAGAIN) { perror ("read"); done = 1; } break; } else if (count == 0) { /* End of file. The remote has closed the connection. */ done = 1; break; } /* Write the buffer to standard output */ s = write (1, buf, count); if (s == -1) { perror ("write"); abort (); } } if (done) { printf ("Closed connection on descriptor %d\n", events[i].data.fd); /* Closing the descriptor will make epoll remove it from the set of descriptors which are monitored. */ close (events[i].data.fd); } } } } free (events); close (sfd); return EXIT_SUCCESS;}
运行方式:
在一个终端运行此程序:a.out PORT
另一个终端:telnet 127.0.0.1 PORT
1 0
- Linux Epool 使用学习笔记
- epool的使用
- epool的使用
- epool使用详解
- epool
- epool
- Linux学习笔记----FTP使用
- 关于epool
- 关于epool
- epool 介绍
- epool实现
- epool详解
- 再论Epool
- select epool
- linux+qtreator+opencv学习笔记-基本使用
- linux下qtreator使用opencv-学习笔记
- linux vi文本工具使用学习笔记
- Linux学习笔记(vim使用命令)
- Add Two Numbers
- spring prototype怎么注入到singleton 里面
- 谈谈 React Native
- Linux下杀死进程(kill)的N种方法
- 利用反射机制创建新类的两种方式及比较
- Linux Epool 使用学习笔记
- NSLog打印优化
- undefined与null的区别
- RocketMQ与Kafka对比(18项差异)
- Office 365 Starter Project for ASP.NET MVC
- 最长单调递增子序列(O(n^2))
- 各种排序法的时间和空间复杂度表
- SDWebImage工作流程
- 数据挖掘十大经典算法