目录
一、背景知识
1.用户空间和内核空间
以4G内存的电脑为例子,系统内核会占1G左右,叫内核空间,其他内存空间就属于用户空间,约3G左右,用户进程不能直接操作内核。对于linux系统,内核空间占高1G字节,用户空间占低3G字节。
2.进程切换
内核有控制进程的能力,进程在运行时,可以被cpu挂起,然后恢复之前挂起的某个进程,这个过程叫进程切换。
3.进程阻塞
例如进程在获取数据时,系统数据没准备好,需要进程等待,这个过程就叫进程阻塞。进程进入阻塞状态时,不占用cpu资源。
4.文件描述符
文件描述符可以理解为文件对应的唯一索引值。
linux系统下,所有文件:普通文件、目录文件、链接文件和设备文件,都可以看作文件。系统启动后,标准输入对应的文件描述符是0,标准输出是1,标准错误是2,此时如果新打开一个文件,其对应的文件描述符就是3,后面以此累加。
int main(int argc, char* argv[]) {
int fd = open("test.py", O_RDONLY);
if (fd == -1) {
return -1;
}
printf("test.py fd = %d \n", fd);
close(fd);
return 0;
}
其中fd就是文件描述符,若系统启动后执行此代码,结果是3
5.缓存I/O
数据从I/O设备读入后,首先进入内核空间的缓存区,然后再由进程从内核空间的缓存区,拷贝到用户进程中。
I/O----->内核缓冲区------>用户进程中
二、I/O模式
1.同步I/O
进程发起I/O操作后,会有等待的过程,也就是会被阻塞
1.阻塞I/O
进程发起I/O操作后,如果没有资源或不能执行,就得进入等待状态,直到可以执行该操作。
2.非阻塞I/O
进程发起I/O操作后,如果没有准备好,会返回一个error,从而不会进入阻塞状态,进程可以继续执行其他任务。
3.I/O多路复用
I/O多路复用,主要解决一个进程同时监控多个网络连接的I/O,基本原理就是select、poll、epoll的function会不断查询所有socket连接,如果有数据到达,就通知用户进程。
2.异步I/O
进程发起I/O操作后,直接返回,不再理睬,剩余工作都交给内核,直到内核发送一个完成信号,此过程就完成了。中间没有阻塞过程。
三、I/O多路复用
1.select
采用遍历文件描述符的方式获取已经就绪的socket
优点:支持所有平台
缺点:单个进程能够监视的文件描述符数量有限,linux下是1024
2.poll
采用遍历文件描述符的方式获取已经就绪的socket
优点:没有最大数量限制
缺点:随着监听数目的增加,效率降低
3.epoll
优点:为解决select和poll的效率问题,epoll不再采用遍历方式,而是使用回调函数,效率不会随着数目增加而降低