博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
i/o多路复用笔记
阅读量:4633 次
发布时间:2019-06-09

本文共 3183 字,大约阅读时间需要 10 分钟。

1、用户空间和内核空间

操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也可以访问底层硬件设备。为了保护用户进程不能直接操作内核,保证内核的安全,操作系统将虚拟空间划分为两部分,一部分是内核空间,一部分是用户空间。

2、进程切换

内核挂起当前正在cpu上运行的进程,并恢复以前挂起的某个进程的执行。

  • 保存处理机上下文,包括程序计数器和其它寄存器。
  • 更新PCB信息
  • 把进程的PCB移入到相应的队列,如就绪或阻塞队列
  • 选择另一个进程执行,并更新PCB
  • 更新内存管理的数据结构
  • 恢复上下文

3、进程阻塞

正在执行的进程,由于期待某些事件的发生,比如IO,自动执行阻塞原语,进入阻塞状态。这是一种主动行为,只有运行中的进程才可以切换到阻塞状态。在阻塞状态的进程是不占用CPU资源的。

4、I/O模式

标准I/O,数据会先被拷贝到操作系统的内核缓冲区,然后才会从操作系统的内核缓冲区拷贝到应用程序的地址空间。

linux有五种网络模式:

  • 阻塞I/O
  • 非阻塞I/O
  • I/O多路复用
  • 信号驱动I/O(signal driven i/o,不常用)
  • 异步I/O

1、阻塞I/O

blocking i/o

用户进程调用recvfrom系统调用,进程进入阻塞状态,等待数据准备好,数据会从内核拷贝到用户内存,然后内核返回结果,用户进程解除block状态,重新运行。

2、非阻塞I/O

nonblocking i/o

用户进程调用read操作,如果数据还没准备好,内核立刻返回error,用户进程不会阻塞。用户进程可以通过反复调用read操作轮询来获得数据。

3、I/O多路复用

I/O multiplexing,也就是select、poll、epoll,也可以被称为event driven I/O。好处是单个进程可以处理多个网络I/O,原理就是select、poll、epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达时,就通知用户进程。

i/o multiplexing

用户进程调用了select,整个进程会被block,同时,kernel会监听所有负责的socket,当有一个socket的数据准备好了,select会返回,用户进程再调用read操作,将数据从内核拷贝到用户进程。如果处理的并发连接数不是很高,使用select、poll、epoll的服务端性能不一定比使用multi-threading + blocking IO的服务端性能好。I/O多路复用时,每一个socket,一般设置为非阻塞模式。

5、I/O多路复用

  • select

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

select函数监视的文件描述符分3类,分别是readfds、writefds、exceptfds。调用select函数会阻塞,直到有描述符就绪或者超时,函数返回。当select函数返回后,可以通过遍历fdset,找到就绪的描述符。

select可以良好的跨平台。缺点是单个进程能够监视的文件描述符的数量存在最大限制。在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制。

  • poll

int poll(struct pollfd *fds, unsigned int nfds, int timeout)struct pollfd {  int fd;  short events; // requested events to watch  short revents; //returned events witnessed}

pollfd结构包含了要监视的event和发生的event,不再使用select『参数-值』传递的方式。pollfd没有最大数量限制,但仍需要轮询返回的pollfd来获取就绪的文件描述符。随着监视的文件描述符数量的增长,效率也会线性下降。

  • epoll

    和select、poll相比,epoll更加灵活,没有描述符的限制。epoll使用一个文件描述符管理多个描述符,将用户进程的文件描述符事件存放在内核的一个事件表中,这样在用户空间和内核空间只需copy一次。
int epoll_create(int size)

创建一个epoll的句柄,size用来告诉内核监听的数目。size并不是限制了epoll所能监听的最大描述符个数,只是对内核初始分配内部数据结构的一个建议。

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

函数对指定描述符fd执行op操作。op取值由三个宏表示:添加EPOLL_CTL_ADD,删除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD。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_data_t data;};//epoll eventsEPOLLIN:表示对应的文件描述符可读(包括对端SOCKET正常关闭)EPOLLOUT: 表示对应的文件描述符可写EPOLLPRI: 表示对应的文件描述符有紧急数据可读(带外数据)EPOLLERR: 表示对应的文件描述法发生错误EPOLLHUP: 表示对应的文件描述法被挂起EPOLLET: 设置为边缘触发EPOLLONESHOT: 只监听一次事件,当监听完这次事件后,如果还需要监听这个socket,需要再次把这个socket加入epoll
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)

参数events表示内核得到的事件的集合。maxevents告知内核这个events有多大,取值不能大于创建epoll_create()时的size。参数timeout时超时时间(ms,0表示立刻返回,-1表示不确定,也有说法是永久堵塞)。该函数返回需要处理的事件数目,如返回0表示已超时。

6、epoll工作模式

两种:LT(level trigger), ET(edge trigger)。缺省是LT。

  • LT: 当epoll_wait检测到描述符事件发生时,将此事件通知应用程序。应用程序可以不立即处理该事件,下次调用epoll_wait时,会再次响应应用程序并通知。
  • ET: 当epoll_wait检测到描述符事件发生时,将此事件通知应用程序。应用程序必须立即处理该事件,下次调用epoll_wait时,不会再次通知此事件。

LT是缺省工作模式,支持block和non-block socket。ET是高速工作模式,只支持non-block。

7、总结

在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描。epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。epoll监视的描述符的数量不受限制,它所支持的FD上限是系统最大可打开文件数目。

转载于:https://www.cnblogs.com/xianzhedeyu/p/6369379.html

你可能感兴趣的文章
TMS320F28335项目开发记录2_CCS与JTAG仿真器连接问题汇总
查看>>
PS多形式的部分之间复制“笨办法”
查看>>
最强的篮球队和马尔可夫模型
查看>>
hdu-4302-Holedox Eating-线段树-单点更新,有策略的单点查询
查看>>
cocos2d-x 音效中断问题
查看>>
设计模式简要笔记
查看>>
子分类账知识学习(汇总网上比较有用的资料)
查看>>
关于JQuery中的ajax请求或者post请求的回调方法中的操作执行或者变量修改没反映的问题...
查看>>
pyQt 每日一练习 -- 登录框
查看>>
wp 删除独立存储空间文件(多级非空文件夹删除)
查看>>
Loadrunner安装使用入门
查看>>
smartupload 上传文件时 把页面编码改成gbk 解决乱码
查看>>
EPS是什么格式
查看>>
新闻网大数据实时分析可视化系统项目——5、Hadoop2.X HA架构与部署
查看>>
【原创】Linux环境下的图形系统和AMD R600显卡编程(11)——R600指令集
查看>>
input禁止显示历史输入记录
查看>>
本日进度6
查看>>
两下或多下回车造成数据库多次提交事物的解决方法
查看>>
Python的数据库操作(Sqlalchemy)
查看>>
2.抽取代码(BaseActivity)
查看>>