[b][size=x-large]基础知识[/size][/b]
[b]1. 文件描述符 fd[/b]
Linux的内核将所有外部设备都可以看做一个文件来操作。那么我们对与外部设备的操作都可以看做对文件进行操作。我们对一个文件的读写,都通过调用内核提供的系统调用;内核给我们返回一个file descriptor(简称:fd,文件描述符);描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性) ; 那么应用程序对文件的读写就通过对描述符的读写完成。
[b]2. 系统调用是如何完成一个I/O操作的呢? [/b]
linux将内存分为内核区,用户区; linux内核给我们管理所有的硬件资源,应用程序通过调用系统调用和内核交互,达到使用硬件资源的目的; 应用程序通过系统调用read发起一个读操作;这时候内核创建一个文件描述符,并通过驱动程序向硬件发送读指令,并将读的的数据放在这个描述符对应结构体的缓存区。但这个结构体是在内核内存区的。需要将这个数据读到用户区。这样完成了一次读操作;
[b]3. IO设备和内存之间的数据传输方式:直接内存访问 DMA[/b]
CPU向DMA控制器下达指令,让DMA控制器来处理数据的传送,DMA控制器通过系统总线来传输数据,传送完毕再通知CPU。
[b]4.什么是IO?[/b]
根据操作设备不同分为:内存IO 网络IO 磁盘IO 等等。内存IO相比后两种足够的快,一般我们只关注后两种IO。
IO的操作需要由内核系统调用来完成,同时系统调用显然需要由CPU来调度,CPU速度非常快,这就导致CPU不得不浪费时间来等待慢速的IO操作。
通过多进程等方式来充分利用空闲的CPU资源,但是还是希望能够让CPU花费足够少的时间在IO操作调度上,这样就可以有更多的CPU时间来完成更多的IO操作。
解决IO的问题,简单总结下就是 如何让高速的CPU和慢速的IO设备更好地协调工作 的问题。
[b][size=x-large]I/O模型[/size][/b]
[b]1. 同步阻塞I/O[/b]
线程阻塞,知道IO就绪才调用IO
[b]2. 同步非阻塞I/O[/b]
进行调用时,如果IO没有就绪,返回错误而非阻塞线程,应用程序循环调用知道IO操作完成
[b]3. 多路复用 (多路I/O就绪通知)[/b]
内核提供系统调用,检查有哪些fd已经就绪,已就绪的fd进行数据复制。
为了解决阻塞IO的问题,出现了IO多路复用模型。多路复用就是用单独的线程(内核级的)来统一等待所有的的socket上的数据,一当某个socket上有数据后,就启用用户线程来copy数据。
- select
优势:支持各个平台
缺点:单进程能只能监控fd限制1024;随着fd的增大复制的开销大;对非活跃状态的TCP,一样会被扫描。
- poll
和select本质一样,只是fd限制没有了
- epoll
epoll基于时间的就绪通知方式。epoll时间通过epoll_ctl()来注册每个文件描述符,一旦某个fd就绪时,内核会回调,激活。
使用mmap机制。
[b]4. I/O信号驱动[/b]
当fd变成就绪状态时,SIGIO会发信号通知用户进程。(只通知一次)
SIGIO是linux2.4下最好的多路IO就绪通知方法。
缺点: 代表事件的信号由内核的事件队列来维护,按照顺序通知,可能会过期,队列长度有限制。
[b]5. 异步I/O (AIO)[/b]
用户进程直接系统调用(aio_read等),有内核进程去处理数据IO,如果数据准备好,内核进程还要把数据拷贝到用户进程,然后通知用户进程,用户进程按照设定的入口函数,去处理异步调用结果,它的异步请求已完成。
所以异步IO其实不需要关注IO的,都是系统内核来解决的。
[b]1. 文件描述符 fd[/b]
Linux的内核将所有外部设备都可以看做一个文件来操作。那么我们对与外部设备的操作都可以看做对文件进行操作。我们对一个文件的读写,都通过调用内核提供的系统调用;内核给我们返回一个file descriptor(简称:fd,文件描述符);描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性) ; 那么应用程序对文件的读写就通过对描述符的读写完成。
[b]2. 系统调用是如何完成一个I/O操作的呢? [/b]
linux将内存分为内核区,用户区; linux内核给我们管理所有的硬件资源,应用程序通过调用系统调用和内核交互,达到使用硬件资源的目的; 应用程序通过系统调用read发起一个读操作;这时候内核创建一个文件描述符,并通过驱动程序向硬件发送读指令,并将读的的数据放在这个描述符对应结构体的缓存区。但这个结构体是在内核内存区的。需要将这个数据读到用户区。这样完成了一次读操作;
[b]3. IO设备和内存之间的数据传输方式:直接内存访问 DMA[/b]
CPU向DMA控制器下达指令,让DMA控制器来处理数据的传送,DMA控制器通过系统总线来传输数据,传送完毕再通知CPU。
[b]4.什么是IO?[/b]
根据操作设备不同分为:内存IO 网络IO 磁盘IO 等等。内存IO相比后两种足够的快,一般我们只关注后两种IO。
IO的操作需要由内核系统调用来完成,同时系统调用显然需要由CPU来调度,CPU速度非常快,这就导致CPU不得不浪费时间来等待慢速的IO操作。
通过多进程等方式来充分利用空闲的CPU资源,但是还是希望能够让CPU花费足够少的时间在IO操作调度上,这样就可以有更多的CPU时间来完成更多的IO操作。
解决IO的问题,简单总结下就是 如何让高速的CPU和慢速的IO设备更好地协调工作 的问题。
[b][size=x-large]I/O模型[/size][/b]
[b]1. 同步阻塞I/O[/b]
线程阻塞,知道IO就绪才调用IO
[b]2. 同步非阻塞I/O[/b]
进行调用时,如果IO没有就绪,返回错误而非阻塞线程,应用程序循环调用知道IO操作完成
[b]3. 多路复用 (多路I/O就绪通知)[/b]
内核提供系统调用,检查有哪些fd已经就绪,已就绪的fd进行数据复制。
为了解决阻塞IO的问题,出现了IO多路复用模型。多路复用就是用单独的线程(内核级的)来统一等待所有的的socket上的数据,一当某个socket上有数据后,就启用用户线程来copy数据。
- select
优势:支持各个平台
缺点:单进程能只能监控fd限制1024;随着fd的增大复制的开销大;对非活跃状态的TCP,一样会被扫描。
- poll
和select本质一样,只是fd限制没有了
- epoll
epoll基于时间的就绪通知方式。epoll时间通过epoll_ctl()来注册每个文件描述符,一旦某个fd就绪时,内核会回调,激活。
使用mmap机制。
[b]4. I/O信号驱动[/b]
当fd变成就绪状态时,SIGIO会发信号通知用户进程。(只通知一次)
SIGIO是linux2.4下最好的多路IO就绪通知方法。
缺点: 代表事件的信号由内核的事件队列来维护,按照顺序通知,可能会过期,队列长度有限制。
[b]5. 异步I/O (AIO)[/b]
用户进程直接系统调用(aio_read等),有内核进程去处理数据IO,如果数据准备好,内核进程还要把数据拷贝到用户进程,然后通知用户进程,用户进程按照设定的入口函数,去处理异步调用结果,它的异步请求已完成。
所以异步IO其实不需要关注IO的,都是系统内核来解决的。