IO多路复用,select、poll、epoll 编程主要步骤

body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}


select

1、int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);

2、void FD_CLR(int fd, fd_set *set);

3、int  FD_ISSET(int fd, fd_set *set);

4、void FD_SET(int fd, fd_set *set);

5、void FD_ZERO(fd_set *set);


fd_set rdset;

FD_ZERO(&rdset);

FD_SET(fd,&rdset);

while(1)

{

FD_ZERO(&rdset);     //每次使用之前都要清空

FD_SET(fd,&rdset);   //集合中加入要监听的描述符

...  //可以监听多个,但是有上限,1024

int ret = select(MAXFD+1,&rdset,NULL,NULL,NULL);  // 第一个参数是最大描述符+1

if(ret>0)

{

if(FD_ISSET(fd,&rdset))  //判断描述符fd是否在rdset集合里面,是就表示有数据可读

{}

}

}


epoll

1、int epoll_create(int size);

2、int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

3、int epoll_wait(int epfd, struct epoll_event *events,

int maxevents, int timeout);


int epfd = epoll_create(1);           //创建一个句柄,区别select内部实现,epoll用的链表,参数非0即可

struct epoll_event event,evs[MAXFD];  //第二个数组是epoll_wait的传出参数

event.events = EPOLLIN;          //监听描述符可读事件

event.data.fd = fd;              //要监听的描述符是fd

epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&event);    //注册事件

event.events = EPOLLIN;

event.data.fd = 0;               //终端标准输入

epoll_ctl(epfd,EPOLL_CTL_ADD,0,&event);

while(1)

{

int ret = epoll_wait(epfd,evs,NUM+1,-1);  //系统中最大能相应NUM个fd,再加上0;

//-1 永久阻塞,知道事件发生

if(ret>0)

{

for(int i=0;i<ret;++i)

{

if(evs[i].events == EPOLLIN && evs[i].data.fd == fd)

{}

}

}

}

event.events == EPOLLIN;

event.data.fd = fd;

epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&events)  //删除一个fd


poll

1、int poll(struct pollfd *fds, nfds_t nfds, int timeout);


int timerfd_create(int clockid, int flags);

int timerfd_settime(int fd, int flags,

const struct itimerspec *new_value,

struct itimerspec *old_value);

int timerfd = timerfd_create(CLOCK_REALTIME,0);

struct itimerspec new_value;

memset(&new_value,0,sizeof(itimerspec));

new_value.it_value.tv_sec = 5;     // 设置初始到期时间

new_value.it_interval.tv_sec = 3;  // 间隔时间

timerfd_settime(timerfd,0,&new_value,NULL);

struct pollfd ppfd;

ppfd.fd = timerfd;

ppfd.events = POLLIN;

while(1)

{

poll(&ppfd,1,-1);  // 永久等待,知道timerfd触发有数据可读

int tmp;

read(timerfd,&tmp,sizeof(int));  // 读走数据,不然定时器异常,一直触发

}


int eventfd(unsigned int initval, int flags);  // 第一个参数是计数器的初始值,第二个为0

int efd = eventfd(0,0);

if(!fork())

{// 子进程

int data = 1;

write(efd,&data,sizeof(int));

}

else

{// 父进程

struct pollfd ppfd;

ppfd.fd = efd;

ppfd.events = POLLIN;

poll(&ppfd,1,-1);  // 永久等待,计数器中写入数据非0的时候可读,等待过程中父进程睡眠(休眠)

int val;

read(efd,&val,sizeof(int));  // 读走数据,计数器自动清0

}

原文地址:https://www.cnblogs.com/meihao1203/p/9368405.html

时间: 2024-11-26 16:35:11

IO多路复用,select、poll、epoll 编程主要步骤的相关文章

转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】

下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理还是有必要的.下面记录下分别基于Select/Poll/Epoll的echo server实现.Python Select Server,可监控事件数量有限制: 1 2 3 4 5 6 7 8 9 10 11 12 13 14

python IO 多路复用 select poll epoll

三个多路复用模型的概念 select select 原理 select 是通过系统调用来监视着一个由多个文件描述符(file descriptor)组成的数组,当select()返回后,数组中就绪的文件描述符会被内核修改标记位(其实就是一个整数),使得进程可以获得这些文件描述符从而进行后续的读写操作.select饰通过遍历来监视整个数组的,而且每次遍历都是线性的. select 优点 select目前几乎在所有的平台上支持,良好跨平台性. select 缺点 每次调用select,都需要把fd集

I/O多路复用 select poll epoll

I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作. select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点

I/O多路复用select/poll/epoll

前言 早期操作系统通常将进程中可创建的线程数限制在一个较低的阈值,大约几百个.因此, 操作系统会提供一些高效的方法来实现多路IO,例如Unix的select和poll.现代操作系统中,线程数已经得到了极大的提升,如NPTL线程软件包可支持数十万的线程. I/O多路复用 select select 允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或指定时间后返回它. select函数原型 #include <sys/select.h> #include <sys/t

python的协程和异步io【select|poll|epoll】

协程又叫做微线程,协程是一种用户态的轻量级的线程,操作系统根本就不知道协程的存在,完全由用户来控制,协程拥有自己的的寄存器的上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切换回来后,恢复之前保存的寄存器的上下文关系,因此协程能保留上一次调用的状态,每次过程重入的时候,就相当于进入上一次调用的状态 协程一定在单线程中,协程的切换是在线程中切换,和单个线程在cpu之间不停的切换是一样的但是线程切换是cpu控制的,而协程的切换是用户控制的,操作系统根本无感知:协程的切换比线程的切换速

非阻塞io模型和io多路复用----select

一.四种io阻塞1.io阻塞:(1 等待数据处于阻塞状态(2从内核copy到用户态处于阻塞状态2.非io阻塞只有从内核copy到用户态处于阻塞状态3.io多路复用----->优势:可以同时监听多个对象(1从check----->ready 通过selec函数来做,处于阻塞状态(2从内核copy到用户态处于阻塞状态3.异步io不用阻塞二.io多路复用select  poll epoll 都属于io同步里面的io多路复用select:轮询问题,监听数量有限poll:提高了监听数量epoll:解决了

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selectors模块 # Python队列/RabbitMQ队列

1 # 进程/线程/协程 2 # IO:同步/异步/阻塞/非阻塞 3 # greenlet gevent 4 # 事件驱动与异步IO 5 # Select\Poll\Epoll异步IO 以及selectors模块 6 # Python队列/RabbitMQ队列 7 8 ############################################################################################## 9 1.什么是进程?进程和程序之间有什么

Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select poll epoll udp组播 线程池

[本文谢绝转载原文来自http://990487026.blog.51cto.com] Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select  poll  epoll udp组播 线程池 TCP 11种状态理解: 1,客户端正常发起关闭请求 2,客户端与服务端同时发起关闭请求 3,FIN_WAIT1直接转变TIME_WAIT 4,客户端接收来自服务器的关闭连接请求 多路IO转接服务器: select模型 poll模型 epoll模型 udp组播模型 线

IO复用之select poll epoll的总结

I/O复用使得程序能够同时监听多个文件描述符,对于提高程序性能至关重要.I/O复用不仅仅在网络程序中使用,但是我接触到的例子中,TCP网络编程那块使用I/O复用比较多,例如,TCP服务器同时处理监听socket和连接socket. 在了解I/O复用之前,我们需要先了解几个概念. 1,同步I/O与异步I/O 2,LT(水平触发)和ET(边缘触发) POSIX把两个术语定义如下: 同步I/O:导致请求进程阻塞,直到I/O操作完成 异步I/O:  不导致请求进程阻塞 阻塞是进程在等待某种资源,但是不能

几种典型的服务器网络编程模型归纳(select poll epoll)

1.同步阻塞迭代模型 同步阻塞迭代模型是最简单的一种IO模型. 其核心代码如下: bind(srvfd); listen(srvfd); for(;;) { clifd = accept(srvfd,...); //开始接受客户端来的连接 read(clifd,buf,...); //从客户端读取数据 dosomthingonbuf(buf); write(clifd,buf)//发送数据到客户端 } 上面的程序存在如下一些弊端: 1)如果没有客户端的连接请求,进程会阻塞在accept系统调用处