IO模型
非阻塞IO
当程序读取硬件数据时,不管硬件数据是否准备好,read()函数不会阻塞,会继续向下执行
程序会不停监测IO事件是否产生,CPU消耗率高
防止进程阻塞在IO函数上,如果要获得有效数据,需要轮循
阻塞IO
当程序读取硬件数据时,如果硬件数据没有准备好,进程会阻塞在read()函数位置,等待硬件数据准备就绪,通过read()函数读取硬件数据后,程序才会向下执行
分为:不可中断休眠状态(D)和可中断休眠状态(S)
常用、简单、效率低,常用于read、write等函数
IO多路复用
需要在一个进程中同时监听多个硬件的数据,使用IO多路复用,IO多路复用实现机制:select、poll、epoll
使用:在用户空间中将监听的事件的文件描述符添加到事件集合中,调用函数进行判断集合中文件描述符对应的硬件数据是否准备就绪,如果没有,则将进程切换到休眠状态(可中断休眠状态);如果有一个或多个硬件数据准备就绪,则将休眠的进程唤醒,对准备就绪的硬件数据进行读写
情景:在使用单进程单线程的情况下,同时处理多个输入输出请求
优点:由于不需要创建新进程和线程,减少了系统的资源开销,减少上下文切换的次数
select:阻塞函数,内核检测指定文件描述符集合中,是否有文件描述符准备就绪
当文件描述符准备就绪后,该函数解除阻塞
当事件产生后,集合中会只剩下触发事件的文件描述符
poll:阻塞函数,内核检测指定文件描述符集合中,是否有文件描述符准备就绪
当文件描述符准备就绪后,该函数解除阻塞
epoll:epoll树、文件描述符表、epoll_create、epoll_ctl、epoll_wait
区别:select:监听的文件描述符有上限,Linux中默认为1024个,每次都需要遍历整个文件描述符集合
poll:监听的文件描述符无上限,每次都需要遍历整个文件描述符集合
epoll:监听的文件描述符无上限,可以快速定位就绪的文件描述符,有效避免了遍历过程