待补充
读取数据:read 与 recv 方法
用户空间和内核空间
用户空间(User Space) 是用户程序运行的空间,比如 nginx、tomcat 等。用户空间只能执行简单的运算,不能直接调用系统的资源,必须通过系统接口(system call)。
内核空间(Kernel Space) 是 Linux 内核的运行空间,我理解就像是系统盘。内核空间可以执行任意命令,调用系统的一切资源。
PIO 与 DMA
PIO: 读取磁盘数据到内存,需要先经过 CPU 存储转发,这样占用 CPU 这个宝贵资源这显然是不合理的。
DMA: 读取磁盘数据到内存,CPU 向 DMA 控制器下达指令,DMA 来处理数据传输,处理完成后再通知 CPU。
缓存 IO 和直接 IO
缓存 IO
缓存 IO 定义:
又称为标准 IO,多数文件系统默认的 IO 都是缓存 IO,在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。
缓存 IO 优点:
- 缓存 I/O 使用了操作系统内核缓冲区,在一定程度上分离了应用程序空间和实际的物理设备。
- 缓存 I/O 可以减少读盘的次数,从而提高性能。
缓存 IO 缺点:
在缓存 I/O 机制中,DMA 方式可以将数据直接从磁盘读到页缓存中,或者将数据从页缓存直接写回到磁盘上,而不能直接在应用程序地址空间和磁盘之间进行数据传输,这样的话,数据在传输过程中需要在应用程序地址空间和页缓存之间进行多次数据拷贝操作,这些数据拷贝操作所带来的 CPU 以及内存开销是非常大的。
缓存 IO 的理解与扩展:
当应用程序尝试读取某块数据的时候,如果这块数据已经存放在了页缓存中,那么这块数据就可以立即返回给应用程序,而不需要经过实际的物理读盘操作。当然,如果数据在应用程序读取之前并未被存放在页缓存中,那么就需要先将数据从磁盘读到页缓存中去。对于写操作来说,应用程序也会将数据先写到页缓存中去,数据是否被立即写到磁盘上去取决于应用程序所采用的写操作机制:如果用户采用的是同步写机制( synchronous writes ), 那么数据会立即被写回到磁盘上,应用程序会一直等到数据被写完为止;如果用户采用的是延迟写机制( deferred writes ),那么应用程序就完全不需要等到数据全部被写回到磁盘,数据只要被写到页缓存中去就可以了。在延迟写机制的情况下,操作系统会定期地将放在页缓存中的数据刷到磁盘上。与异步写机制( asynchronous writes )不同的是,延迟写机制在数据完全写到磁盘上的时候不会通知应用程序,而异步写机制在数据完全写到磁盘上的时候是会返回给应用程序的。所以延迟写机制本身是存在数据丢失的风险的,而异步写机制则不会有这方面的担心。
直接 IO
直接 IO 定义:
数据从磁盘通过 DMA 直接 copy 到用户空间,直接 IO 的数据均直接在用户地址空间的缓冲区和磁盘之间直接进行传输,完全不需要页缓存的支持。
直接 IO 优点:
直接 IO 可以将主动权掌握在应用程序手中,避免内核空间出现问题对应用程序造成影响,绕过内核缓冲区也可以减少系统内存的开销,因为内核缓冲区本身就在使用系统内存。
直接 IO 缺点:
如果访问的数据不在应用程序缓存中,那么每次数据都会直接从磁盘进行加载,这种直接加载会非常缓慢。通常直接 I/O 跟异步 I/O 结合使用会得到较好的性能。
直接 IO 的理解与扩展:
凡是通过直接 I/O 方式进行数据传输,数据均直接在用户地址空间的缓冲区和磁盘之间直接进行传输,完全不需要页缓存的支持。操作系统层提供的缓存往往会使应用程序在读写数据的时候获得更好的性能,但是对于某些特殊的应用程序,比如说数据库管理系统这类应用,他们更倾向于选择他们自己的缓存机制,因为数据库管理系统往往比操作系统更了解数据库中存放的数据,数据库管理系统可以提供一种更加有效的缓存机制来提高数据库中数据的存取性能。
同步 IO&异步 IO
同步 IO
- 同步 IO: 类似 API 接口,用户空间发送请求之后等待内核空间拿到数据给用户空间返回,这段时间内处于等待状态是不能干其他事情的。
异步 IO
- 异步 IO: 标准的异步处理流程,内核空间接收到请求之后立刻返回(可以去做其他事情了),然后内核空间找到数据之后通过回调的方式将数据给到用户空间。
同步阻塞 IO&同步非阻塞 IO
同步阻塞 IO
- 同步阻塞 IO 模型:
- 同步阻塞 IO 理解:
阻塞 IO 使用 recv 的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。类似于去食堂打饭,一直等待打完饭后离开,若食堂的饭还没有准备好那么也一直等待到饭做好为止才能离开去做别的事情。
同步非阻塞 IO
- 同步非阻塞 IO 模型:
- 同步非阻塞 IO 理解:
非阻塞 IO 改变 flags,让 recv 不管有没有获取到数据都返回,如果没有数据那么一段时间后再调用 recv 看看,如此循环。同样使用食堂打饭来打比方,这次小朋友学聪明了,跑到食堂后看到饭还没有做好,他就先去做其他事情,过一会再来看看,但是打饭的过程中还是要等着把饭打满的。所以说非阻塞队列是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于