Epoll 支持管道,FIFO,套接字,POSIX消息队列,终端,设备等,但就是不支持普通文件!!
1、epoll函数详解:
1.1创建监听池:
int epoll_creat(int size);
int epoll_create1(int flags);
创建epoll监听池,第一个函数从2.6.8版本之后不在有入口参数size。
入口参数:第二个函数的入口参数是创建标志,一般我们让他等于0,此时两个函数的功能一模一样。
返回值:所创建监听池的fd
1.2:添加要监听的事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
入口参数:
epfd:监听池的fd
op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除
fd:需要监听文件的fd
epoll_event:指向epoll_event的指针;
如果调用成功返回0,不成功返回-1
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
其中events取值:EPOLLIN 可读、EPOLLOUT 可写
data:可以写文件的fd
1.3:等待事件的发生
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
入口参数:
epfd:监听池fd
events:事件数组,来存储已经发生的事件
maxevents:允许事件的最大数目
timeout:超时时间(当timeout=-1的时候,会一直等)
返回值:有事件发生:发生事件的个数、没有事件发生:0、错误:-1
2、epoll函数示例:test.c利用epoll机制监听两个FIFO、client.c向两个fifo中写入,以满足可读的要求
test.c:
#include <stdio.h>
#include <sys/epoll.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main()
{
int fd1,fd2;
//创建FIFO
int efd;
struct epoll_event Events;
struct epoll_event *Es;
int n;
int i;
mkfifo("/tmp/fifo1",0666);
mkfifo("/tmp/fifo2",0666);
fd1 = open("/tmp/fifo1",O_RDWR);
fd2 = open("/tmp/fifo2",O_RDWR);
//创建监听池
efd = epoll_create1(0);
//构造监听事件,加入监听池
Events.events = EPOLLIN | EPOLLET; //设置为读事件,并设置为边沿触发
Events.data.fd = fd1;
epoll_ctl(efd,EPOLL_CTL_ADD,fd1,&Events);
Events.events = EPOLLIN | EPOLLET; //设置为读事件,并设置为边沿触发
Events.data.fd = fd2;
epoll_ctl(efd,EPOLL_CTL_ADD,fd2,&Events);
//为Es数组分配内存
Es = calloc(100,sizeof(Events));
n = epoll_wait(efd,Es,100,-1);
for(i = 0;i < n;i++)
{
if(Es[i].events & EPOLLIN)
{
printf("file %d can be read\n",Es[i].data.fd);
}
if(Es[i].events & EPOLLOUT)
{
}
}
free(Es);
close(fd1);
close(fd2);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int fd1,fd2;
char c[5] = "Hello";
fd1 = open("/tmp/fifo1",O_RDWR);
fd2 = open("/tmp/fifo2",O_RDWR);
if(*argv[1] == '1')
write(fd1,c,5);
if(*argv[1] == '2')
write(fd2,c,5);
close(fd1);
close(fd2);
}
编译之后,先在一个终端中运行test,在另一个终端中运行client
./client 1:向FIFO1中写入
./client 2:向FIFO2中写入