epoll_create
open an epoll file descriptor
SYNOPSIS
#include <sys/epoll.h>
int epoll_create(int size)
DESCRIPTION
Open an epoll file descriptor by requesting the kernel allocate an event backing store dimensioned for size descriptors. The size is not the maximum size of the backing store but just a hint to the kernel about how to dimension internal structures. The returned file descriptor will be used for all the subsequent calls tothe epoll interface. The file descriptor returned by epoll_create(2) must be closed by using close(2).
RETURN VALUE
When successful, epoll_create(2) returns a non-negative integer identifying the descriptor. When an error occurs, epoll_create(2) returns -1 and errno is set appropriately.ERRORS
EINVAL size is not positive.ENFILE The system limit on the total number of open files has been reached.
ENOMEM There was insufficient memory to create the kernel object.
CONFORMING TO epoll_create(2) is a new API introduced in Linux kernel 2.5.44. The interface should be finalized by Linux kernel 2.5.66.
创建句柄或者文件描述符,特别注意,epoll并不是所有的内核版本都支持
epoll_ctl
control interface for an epoll descriptorSYNOPSIS
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
DESCRIPTION
Control an epoll descriptor, epfd, by requesting that the operation op be performed on the target file descriptor, fd. The event describes the object linked to thefile descriptor fd. The struct epoll_event is defined as :
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 */
};
EVENT
The events member is a bit set composed using the following available event types :EPOLLIN
The associated file is available for read(2) operations.
EPOLLOUT
The associated file is available for write(2) operations.
EPOLLRDHUP
Stream socket peer closed connection, or shut down writing half of connection. (This flag is especially useful for writing simple code to detect peer shutdown when using Edge Triggered monitoring.)
EPOLLPRI
There is urgent data available for read(2) operations.
EPOLLERR
Error condition happened on the associated file descriptor. epoll_wait(2) will always wait for this event; it is not necessary to set it in events.
EPOLLHUP
Hang up happened on the associated file descriptor. epoll_wait(2) will always wait for this event; it is not necessary to set it in events.
EPOLLET
Sets the Edge Triggered behaviour for the associated file descriptor. The default behaviour for epoll is Level Triggered. See epoll(7) for more detailed information about Edge and Level Triggered event distribution architectures.
EPOLLONESHOT (since kernel 2.6.2)
Sets the one-shot behaviour for the associated file descriptor. This means that after an event is pulled out with epoll_wait(2) the associated file descriptor is internally disabled and no other events will be reported by the epoll interface. The user must call epoll_ctl(2) with EPOLL_CTL_MOD to reenable the file descriptor with a new event mask.
The epoll interface supports all file descriptors that support poll(2). Valid values for the op parameter are :
EPOLL_CTL_ADD
Add the target file descriptor fd to the epoll descriptor epfd and associate the event event with the internal file linked to fd.
EPOLL_CTL_MOD
Change the event event associated with the target file descriptor fd.
EPOLL_CTL_DEL
Remove the target file descriptor fd from the epoll file descriptor, epfd. The event is ignored and can be NULL (but see BUGS below).
RETURN VALUE
When successful, epoll_ctl(2) returns zero. When an error occurs, epoll_ctl(2) returns -1 and errno is set appropriately.ERRORS
EBADF epfd or fd is not a valid file descriptor.EEXIST op was EPOLL_CTL_ADD, and the supplied file descriptor fd is already in epfd.
EINVAL epfd is not an epoll file descriptor, or fd is the same as epfd, or the requested operation op is not supported by this interface.
ENOENT op was EPOLL_CTL_MOD or EPOLL_CTL_DEL, and fd is not in epfd.
ENOMEM There was insufficient memory to handle the requested op control operation.
EPERM The target file fd does not support epoll.
CONFORMING TOepoll_ctl(2) is a new API introduced in Linux kernel 2.5.44. The interface should be finalized by Linux kernel 2.5.66.
BUGS
In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-NULL pointer in event, even though this argument is ignored. Since kernel 2.6.9, event can be specified as NULL when using EPOLL_CTL_DEL.
事件注册,将监控的描述符加入监控或者取消监控
epoll_wait
wait for an I/O event on an epoll file descriptor
SYNOPSIS
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event * events,int maxevents, int timeout);
DESCRIPTION
Wait for events on the epoll file descriptor epfd for a maximum time of timeout milliseconds. The memory area pointed to by events will contain the events that will be available for the caller. Up to maxevents are returned by epoll_wait(2). The maxevents parameter must be greater than zero. Specifying a timeout of -1 makes epoll_wait(2) wait indefinitely, while specifying a timeout equal to zero makes epoll_wait(2) to return immediately even if no events are available (return code equal to zero). The struct epoll_event is defined as :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 */
};
The data of each returned structure will contain the same data the user set with a epoll_ctl(2) (EPOLL_CTL_ADD,EPOLL_CTL_MOD) while the events member will contain the returned event bit field.
RETURN VALUE
When successful, epoll_wait(2) returns the number of file descriptors ready for the requested I/O, or zero if no file descriptor became ready during the requestedtimeout milliseconds. When an error occurs, epoll_wait(2) returns -1 and errno is set appropriately.
ERRORS
EBADF epfd is not a valid file descriptor.EFAULT The memory area pointed to by events is not accessible with write permissions.
EINTR The call was interrupted by a signal handler before any of the requested events occurred or the timeout expired.
EINVAL epfd is not an epoll file descriptor, or maxevents is less than or equal to zero.
CONFORMING TO epoll_wait(2) is a new API introduced in Linux kernel 2.5.44. The interface should be finalized by Linux kernel 2.5.66.
常用形式:
struct epoll_event ev, *events;
for(;;)
{
nfds = epoll_wait(kdpfd, events, maxevents, -1);
for(n = 0; n < nfds; ++n)
{
if(events[n].data.fd == listener)
{
client = accept(listener, (struct sockaddr *) &local,&addrlen);
if(client < 0)
{
perror("accept");
continue;
}
setnonblocking(client);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = client;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0)
{
fprintf(stderr, "epoll set insertion error: fd=%d\n",client);
return -1;
}
}
else
do_use_fd(events[n].data.fd);
}
}
我写的代码
[fy@localhost socket_epoll]$ less epoll.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#define RELEASE
#define DEBUG
#define MYPORT 80 // the port users will be connecting to
#define BACKLOG 5 // how many pending connections queue will hold
#ifndef INFTIM
#define INFTIM -1
#endif
#define BUF_SIZE 500000
#define MAXLINE 100
#define MAXCLIENT 5
int fd_access[BACKLOG]; // accepted connection fd
int conn_amount; // current connection amount
int recv_number=0;
void setnonblocking(int sock)
{
int opts;
opts=fcntl(sock,F_GETFL);
if(opts<0)
{
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0)
{
perror("fcntl(sock,SETFL,opts)");
exit(1);
}
}
int main(void)
{
int sock_fd, new_fd,len,listen_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in server_addr; // server address information
struct sockaddr_in client_addr; // connector's address information
socklen_t sin_size;
char buf[BUF_SIZE];
int result;
int i,j;
int maxsock=0;
int conn_fd,epfd,n;
#ifdef DEBUG
printf("hello debug\n");
#endif
if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
setnonblocking(listen_fd);
server_addr.sin_family = AF_INET; // host byte order
server_addr.sin_port = htons(MYPORT); // short, network byte order
server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));
if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
{
perror("bind");
exit(1);
}
if (listen(listen_fd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
#ifdef DEBUG
printf("listen port %d listen_fd %d\n", MYPORT,listen_fd);
#endif
//epoll
struct epoll_event ev,events[20];
epfd=epoll_create(1024);
printf("%d---%d\n",epfd,epoll_create(600));
ev.data.fd=listen_fd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,listen_fd,&ev);
ev.data.fd=12;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,listen_fd,&ev);
sin_size = sizeof(client_addr);
#ifdef DEBUG
printf("EPOLLIN---%d",EPOLLIN);
#endif
while (1)
{
result=epoll_wait(epfd,events,20,-1);
#ifdef DEBUG
printf("the total number is %d\n",recv_number);
printf("result is %d \n",result);
#endif
for(i = 0; i <result; i++)
{
#ifdef DEBUG
printf("--------------print events----------------\n");
for(j=0;j<result;j++)
{
printf("j events %d\n",events[j].events);
printf("j data fd %d\n",events[j].data.fd);
}
printf("--------------print events over-----------\n");
#endif
if(events[i].data.fd==listen_fd)
{
new_fd=accept(listen_fd,(struct sockaddr*)&client_addr,&sin_size);
while(new_fd>0)
{
#ifdef DEBUG
printf("new_fd -------%d\n",new_fd);
setnonblocking(new_fd);
#endif
ev.data.fd=new_fd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,new_fd,&ev);
new_fd=accept(listen_fd,(struct sockaddr*)&client_addr,&sin_size);
}
}
else if(events[i].events&EPOLLIN)
{
#ifdef DEBUG
printf("mark %d\n",events[i].data.fd);
#endif
if ( (sock_fd = events[i].data.fd) < 0)
{
printf("just do it \n");
continue;
}
#ifdef DEBUG
printf("sock_fd ------%d\n",sock_fd);
#endif
n = recv(sock_fd, buf,5,0);
recv_number+=n;
sleep(2);
#ifdef DEBUG
printf("recv n ----%d\n",n);
#endif
if(n< 0)
{
printf("mark1");
if (errno == ECONNRESET)
{
close(sock_fd);
events[i].data.fd = -1;
}
else
printf("sorry \n");
}
else if (n == 0)
{
close(sock_fd);
events[i].data.fd = -1;
}
buf[n] = '\0';
printf("read data %s\n",buf);
ev.data.fd=sock_fd;
ev.events=EPOLLOUT|EPOLLET;
epoll_ctl(epfd, EPOLL_CTL_MOD, sock_fd, &ev);
}
else if(events[i].events&EPOLLOUT)
{
sock_fd = events[i].data.fd;
write(sock_fd, buf, n);
ev.data.fd=sock_fd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,sock_fd,&ev);
}
}
}
exit(0);
}
(END)
可以客户端,见本博客,注意改下端口
http://blog.csdn.net/xluren/article/details/8043484