Linux基础之I/O复用

来源:互联网 发布:自制松露巧克力 知乎 编辑:程序博客网 时间:2024/05/27 01:16
最好的参考资料:
1.网络资料。
2.UNP v1第6章 。(注:UNIX 网络编程,很经典的书,推荐!!)

第一条:概述

复用是个伟大的概念呀!什么是I/O复用(I/O multiplexing)呢?具体点就是当你编写的程序需要同时处理多个描数字(socket或file或device),你又不知道什么时候应该(比方说有数据可以读了)去操作(读/写)哪个描数字。这时候I/O复用就需要登场了。

UNPv1给出了定义。I/O复用是一种让进程预先“警告”内核能力,使得内核一旦发现进程预先告知时指定的一个或多个I/O条件(就是描述符)就绪(可以读/写了),内核就通知进程。

linux有4个调用可实现I/O复用:select、poll继承自Unix系统。pselect是select到Posix版。epoll是linux2.6内核特有的。


第二条:I/O模型

(1)一般输入操作通常包含如下两个阶段,请谨记:
1、等待数据准备好。

2、内核到进程的数据拷贝。


(2)例如对于socket上的输入操作:
1、数据从网络到达,当数据到达时,收集到内核中相应的缓冲区。

2、从内核缓冲区拷贝数据到进程端口缓冲区中。


(1)UNPv1当中总结了Unix的I/O模型:

1、阻塞I/O:进程被阻塞I/O系统调用上(read、write、sendto、recvfrom等等)直到I/O条件就绪(可读/写或异常)处理完,处理后从I/O系统调用返回进程。
2、非阻塞I/O。就是采用轮询方式调用非阻塞I/O系统调用。
3、I/O复用。
4、信号驱动I/O。类似于I/O复用,当I/O条件就绪时使用信号通知进程去调用I/O系统调用处理。
5、异步I/O。通过aio_read告诉内核怎么处理,我们就不管了,内核处理完了后发个信号告诉我们,也可以用其他方式在处理完通知我们。

注:I/O系统调用是否阻塞,仅取决于他们操作的描数字是否是阻塞的。fcntl可设定。

原文:

  • blocking I/O


  • nonblocking I/O


  • I/O multiplexing (select and poll)


  • signal driven I/O (SIGIO)


  • asynchronous I/O (the POSIX aio_functions)



(2)这6种I/O模型分为2类:

同步I/O模型:第1~4 I/O模型。这5种I/O模型,说到底,I/O调用还是要用户进程自己调用,被阻塞。
异步I/O模型:第5种I/O模型。I/O调用由内核执行,进程不被阻塞。
Posix关于同步I/O(synchronous I/O操作、异步I/O(asynchronous I/O)操作这两个术语的定义如下:
同步I/O操作:导致请求进程阻塞,直到I/O操作完成。
异步I/O操作:不导致进程阻塞。

注:鉴别是否是异步I/O操作,只要看I/O操作是谁执行。


以下还未认真理解分析。

poll

 
#include <poll.h>
(0)int poll(struct pollfd fds[], nfds_t nfds, int timeout);//epoll是poll的增强版
 
(0.1)参数fds是指向struct pollfd的数组。他是poll的核心。  
struct pollfd{//每个描述符对应一个struct pollfd结构。
    int fd; //我们关心的描述符。
    short int events; //描述符关心的事件
    short int revents; //poll返回时,返回描述符fd发生的时间。
  };
成员events和revents的值如下:
 
 
#define POLLIN 0x001 //可读
#define POLLPRI 0x002 //带外数据到达
#define POLLOUT 0x004 可写
#if defined __USE_XOPEN || defined __USE_XOPEN2K8  //很少用
# define POLLRDNORM 0x040 //一般数据可读
# define POLLRDBAND 0x080 //优先级带数据可读
# define POLLWRNORM 0x100 //一般数据可读
# define POLLWRBAND 0x200 //优先级数据可写
#endif
#ifdef __USE_GNU
# define POLLMSG 0x400
# define POLLREMOVE 0x1000
# define POLLRDHUP 0x2000
#endif
 
#define POLLERR 0x008 错误
#define POLLHUP 0x010 挂起
#define POLLNVAL 0x020 //无效描述符等
 
(0.2)参数nfds:指名数组大小。
(0.3)参数timeout:超时时间。取值如下,单位为毫秒:
INFTIM:永远等待。linux没有定义此值,手动定义为-1即可。
0:立即返回,不阻塞进程。
>0:等待指定毫秒数。
第五条:FAQ
1、epoll是poll的加强版。
 
 
2、poll没有select 的描述符上限限制。描述符个数上限只和内存大小结构,即内存中struct pollfd 的个数。