1. 5种IO模型:
(1)blocking IO - 阻塞IO
(2)nonblocking IO - 非阻塞IO
(3)IO multiplexing - IO多路复用
(4)signal driven IO - 信号驱动IO
(5) asynchronous IO - 异步IO
其中前面4种IO都可以归类为synchronous IO - 同步IO,signal driven IO平时用的比较少。
2.Select:
不断地轮询所负责的所有socket,当某个socket有数据到达时,就通知用户进程。(默认是1024)
(1)实现:
当用户process调用select的时候,select会将需要监控的fds集合拷贝到内核空间(假设监控的仅仅是socket可读),然后遍历自己监控的socket sk,挨个调用sk的poll逻辑以便检查该sk是否有可读事件,遍历完所有的sk后,如果没有任何一个sk可读,那么select会调用schedule_timeout进入schedule循环,使得process进入睡眠。如果在timeout时间内某个sk上有数据可读了,或者等待timeout了,则调用select的process会被唤醒,接下来select就是遍历监控的sk集合,挨个收集可读事件并从内核态拷贝到用户态。
select为每个socket引入一个poll逻辑,该poll逻辑用于收集socket发生的事件。poll函数返回一个描述读写是否就绪的mass掩码,根据掩码对fd_set赋值
通过上面的select逻辑过程分析,select存在两个问题:
A. 被监控的fds需要从用户空间拷贝到内核空间。为了减少数据拷贝带来的性能损坏,内核对被监控的fds集合大小做了限制,并且这个是通过宏控制的,大小不可改变(限制为1024)。
B. 被监控的fds集合中,只要有一个有数据可读,整个socket集合就会被遍历一次调用sk的poll函数收集可读事件。由于当初的需求是朴素,仅仅关心是否有数据可读这样一个事件,当事件通知来的时候,由于数据的到来是异步的,我们不知道事件来的时候,有多少个被监控的socket有数据可读了,于是,只能挨个遍历每个socket来收集可读事件。
3. epoll
Int epoll_creat( int size); 创建一个epoll fd。
Int epoll_ctl( int epfd, int op, int fd, struct epoll_evevt