linux进程多路复用技术,Linux之I/O多路复用

I/O多路复用:单个线程可以同时处理多个I/O;

一、select:成功则返回已准备好的文件描述符个数,超时则返回0,出错则返回-1;

(1)头文件包含:#include 、、;

(2)select返回后集合fdset中只有事件发生了的fd对应的位被置为1,其他位都被清空为0,所以需要依次用FD_ISSET来判断是否被置为1即事件是否发生;

int select(int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tvptr);

int FD_ZERO(fd_set *fdset);---删除集合fdset中的所有文件描述符

int FD_SET(int fd, fd_set *fdset);---加入fd到集合fdset中

int FD_CLR(int fd, fd_set *fdset);---删除集合fdset中的fd

int FD_ISSET(int fd, fd_set *fdset);---判断fd为是否可读写

f0d94a9d0777eb7e96829ceabbd96a50b46.jpg

5b6d9ef40afb5f82f3fe75e114bfb2cc032.jpg

1 #include

2 #include

3

4 int main(int argc, char *argv[])5 {6 fd_set readset, writeset;7 int ret = 0;8 FD_ZERO(&readset);9 FD_ZERO(&writeset);10 FD_SET(3, &readset);11 FD_SET(5, &writeset);12

13 ret = select(6, &readset, &writeset, NULL, NULL);14 switch(ret)15 {16 case -1: //error

17 break;18 case 0: //timeout

19 break;20 default: //success

21 if(FD_ISSET(3, &readset))22 {23 ;//read fd(3)

24 }25 if(FD_ISSET(5, &writeset))26 {27 ;//write fd(5)

28 }29 break;30 }31 return 0;32 }

View Code

二、poll:成功则返回已准备好的文件描述符个数,超时则返回0,出错则返回-1;

(1)头文件包含:#include

(2)struct pollfd

{

int fd;

short events; //input: interested event

short revents; //output: occured event

};

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

ff03f80f70f4ac95c7587d7bc95a31b5e23.jpg

91c2e1b25d74705dc99800c76a6896332dd.jpg

1 #include

2 #define EVENTS_NUM 3

3

4 int main(int argc, char *argv[])5 {6 structpollfd pfds[EVENTS_NUM];7 int ret = 0;8

9 pfds[0].fd = 10;10 pfds[0].events =POLLIN;11 pfds[1].fd = 11;12 pfds[1].events =POLLOUT;13 pfds[2].fd = 12;14 pfds[2].events =POLLERR;15

16 ret = poll(pfds, EVENTS_NUM, -1);17 switch(ret)18 {19 case -1: //error

20 break;21 case 0: //timeout

22 break;23 default: //success

24 for(int i = 0; i < EVENTS_NUM; i++)25 {26 if(pfds[i].revents &POLLIN)27 {28 //read pfds[i].fd

29 }30 else if(pfds[i].revents &POLLOUT)31 {32 //write pfds[i].fd

33 }34 else if(pfds[i].revents &POLLERR)35 {36 //handle pfds[i].fd

37 }38 }39 break;40 }41 return 0;42 }

View Code

三、epoll:成功则返回已准备好的文件描述符个数,超时则返回0,出错则返回-1;

(1)头文件包含:#include ,epoll是一种当文件描述符的内核读缓冲区非空的时候发出可读signal通知进程;当内核写缓冲区不满的时候发出可写signal通知进程的机制,即事件驱动的机制;

(2)LT:水平触发(Level Triggered),如果对就绪的文件描述符fd不做操作,则内核会一直通知直到fd被处理为止;默认值,传统的select/poll也采用该机制;

(3)ET:边缘触发(Edge Triggerred),不管有没有对就绪的文件描述符fd做操作,内核之通知一次;

int epoll_create(int size);

int epoll_ctl(int efpd, int op, int fd, struct epoll_event *event);

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

int close(int epfd);

37b0dd141b7715f7e40b2ad8fcf3e889f12.jpg

f2fbe136ed87069ed6b9e057bbb4d3b397a.jpg

1 #include

2 #include //eventfd,create a fd which is used to event-notify

3 #define EVENT_NUM 3

4

5 int main(int argc, char *argv[])6 {7 int epfd, ret = 0;8 struct epoll_event tmpEvt, occuredEvts[20];9

10 epfd = epoll_create(256);11 if(epfd < 0)12 {13 //error

14 }15 for(int i = 0; i < EVENT_NUM; i++)16 {17 tmpEvt.data.fd = eventfd(0, EFD_CLOEXEC |EFD_NONBLOCK);18 //tmpEvt.data.fd = i;

19 tmpEvt.events =EPOLLIN;20 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, i, &tmpEvt);21 if(ret < 0)22 {23 //error

24 }25 }26 ret = epoll_wait(epfd, occuredEvts, EVENT_NUM, -1);27 switch(ret)28 {29 case -1: //error

30 break;31 case 0: //timeout

32 break;33 default: //success

34 for(int i = 0; i < ret; i++) //traverse ret!!!!!!

35 {36 if(occuredEvts[i].events &EPOLLIN)37 {38 //read occuredEvts[i].data.fd

39 }40 else if(occuredEvts[i].events &EPOLLOUT)41 {42 //write occuredEvts[i].data.fd

43 }44 else if(occuredEvts[i].events &EPOLLERR)45 {46 //handle occuredEvts[i].data.fd

47 }48 }49 break;50 }51

52 return 0;53 }

View Code

四、select/poll/epoll之间的比较

1 select:需要将用户传入的集合拷贝到内核空间,然后遍历每个fd对应的设备状态,如果设备就绪就更新设备的状态并继续遍历;如果遍历完没有发现就绪的设备则挂起当前进程,直到有设备就绪或者超时,进程被唤醒后又要遍历每个fd;最大连接数1024或2048;

2 poll:和select机制类似,唯一不同的就是poll没有最大连接数的限制,因为poll内部是基于链表(传入数组头指针+长度)来存储的;

3 epoll:内核监听到某个fd就绪时,就会采用callback函数的机制把该fd放入到内核的就绪队列中,这样epoll_wait返回的时候就只需要遍历该就绪队列即可,而无需遍历所有的fd;内核用红黑树来管理传入的epfd即多个fd;

(1)没有最大连接数的限制,1G的内存可以监听10万个fd;

(2)当fd就绪时它只会遍历已经就绪的fd,时间复杂度O(1),而不会像select/poll那样线性遍历所有的fd,所以效率得到了提升;

(3)采用内存映射(mmap)技术,减少了内存拷贝的开销;

06449898cc430145305a60fa295ab65d.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值