diff --git a/README.md b/README.md index e8e21c79..7019babf 100644 --- a/README.md +++ b/README.md @@ -189,7 +189,8 @@ * [后端程序员必备的 Linux 基础知识](docs/operating-system/linux.md) * [Shell 编程入门](docs/operating-system/Shell.md) -* [完全使用GNU_Linux学习](docs/operating-system/完全使用GNU_Linux学习.md) +* [我为什么从Windows转到Linux?](docs/operating-system/完全使用GNU_Linux学习.md) +* [Linux IO模型](docs/operating-system/Linux_IO.md) * [Linux 性能分析工具合集](docs/operating-system/Linux性能分析工具合集.md) ## 数据结构与算法 diff --git a/docs/operating-system/Linux_IO.md b/docs/operating-system/Linux_IO.md index a69315df..7cd00cd6 100644 --- a/docs/operating-system/Linux_IO.md +++ b/docs/operating-system/Linux_IO.md @@ -18,27 +18,25 @@ # Linux IO -**图源: -[简书](https://www.jianshu.com/p/85e931636f27) (如有侵权,请联系俺,俺会立刻删除)** +> 图源: https://www.jianshu.com/p/85e931636f27 (如有侵权,请联系俺,俺会立刻删除) ### 操作系统的内核 -操作系统的内核是操作系统的核心部分。 -它负责系统的内存,硬件设备,文件系统以及应用程序的管理。 +**操作系统的内核是操作系统的核心部分。它负责系统的内存,硬件设备,文件系统以及应用程序的管理。** #### 操作系统的用户态与内核态 -unix与linux的体系架构:分为用户态与内核态。 +unix与linux的体系架构:用户态与内核态。 + 用户态与内核态与内核态是操作系统对执行权限进行分级后的不同的运行模式。 ![用户态与内核态](../../media/pictures/java/linux_io/用户态与内核态.png) #### 为什么要有用户态与内核态? -在cpu的所有指令中,有些指令是非常危险的,如果使用不当,将会造成系统崩溃等后果。 -为了避免这种情况发生,cpu将指令划分为**特权级(内核态)指令**和**非特权级(用户态)指令。** +在cpu的所有指令中,有些指令是非常危险的,如果使用不当,将会造成系统崩溃等后果。为了避免这种情况发生,cpu将指令划分为**特权级(内核态)指令**和**非特权级(用户态)指令。** **对于那些危险的指令只允许内核及其相关模块调用,对于那些不会造成危险的指令,就允许用户应用程序调用。** @@ -75,8 +73,8 @@ unix与linux的体系架构:分为用户态与内核态。 #### 同步与异步 -1. 同步: 一个线程调用一个方法计算 1 - 100 的和,如果方法没有计算完,就不返回。 -2. 异步: 一个线程调用一个方法计算 1 - 100 的和,该方法立刻返回,但是由于方法没有返回结果, +1. **同步**: 一个线程调用一个方法计算 1 - 100 的和,如果方法没有计算完,就不返回。 +2. **异步**: 一个线程调用一个方法计算 1 - 100 的和,该方法立刻返回,但是由于方法没有返回结果, 所以就需要被调用的这个方法来通知调用线程 1 - 100的结果, 或者线程在调用方法的时候指定一个回调函数来告诉被调用的方法执行完后就执行回调函数。 @@ -93,12 +91,7 @@ Linux下共有5种IO模型: 5. 异步IO #### 阻塞IO -阻塞IO是很常见的一种IO模型。 -在这种模型中,**用户态的应用程序会执行一个操作系统的调用, -检查内核的数据是否准备好。如果内核的数据已经准备好, -就把数据复制到用户应用进程。如果内核没有准备好数据, -那么用户应用进程(线程)就阻塞,直到内核准备好数据并把数据从 -内核复制到用户应用进程,** 最后应用程序再处理数据。 +阻塞IO是很常见的一种IO模型。在这种模型中,**用户态的应用程序会执行一个操作系统的调用,检查内核的数据是否准备好。如果内核的数据已经准备好,就把数据复制到用户应用进程。如果内核没有准备好数据,那么用户应用进程(线程)就阻塞,直到内核准备好数据并把数据从内核复制到用户应用进程,** 最后应用程序再处理数据。 ![BIO原理](../../media/pictures/java/linux_io/BIO原理.png) @@ -107,44 +100,28 @@ Linux下共有5种IO模型: 1. 阻塞IO的同步体现在: **内核只有准备好数据并把数据复制到用户应用进程才会返回。** 2. 阻塞IO的阻塞体现在:**用户应用进程等待内核准备数据和把数据从用户态拷贝到内核态的这整个过程, -用户应用进程都必须一直等待。** -当然,如果是本地磁盘IO,内核准备数据的时间可能会很短。 -但网络IO就不一样了,因为服务端不知道客户端何时发送数据, -内核就仍需要等待socket数据,时间就可能会很长。 +用户应用进程都必须一直等待。** 当然,如果是本地磁盘IO,内核准备数据的时间可能会很短。但网络IO就不一样了,因为服务端不知道客户端何时发送数据,内核就仍需要等待socket数据,时间就可能会很长。 -**阻塞IO的优点是对于数据是能够保证无延时的,因为应用程序进程会一直阻塞直到IO完成。** -但应用程序的阻塞就意味着应用程序进程无法执行其他任务, -这会大大降低程序性能。一个不太可行的办法是为每个客户端socket都分配一个线程, -这样就会提升server处理请求的能力。不过操作系统的线程资源是有限的, -如果请求过多,可能造成线程资源耗尽,系统卡死等后果。 +**阻塞IO的优点是对于数据是能够保证无延时的,因为应用程序进程会一直阻塞直到IO完成。**但应用程序的阻塞就意味着应用程序进程无法执行其他任务,这会大大降低程序性能。一个不太可行的办法是为每个客户端socket都分配一个线程,这样就会提升server处理请求的能力。不过操作系统的线程资源是有限的,如果请求过多,可能造成线程资源耗尽,系统卡死等后果。 #### 非阻塞IO(网络IO模型) -在非阻塞IO模型中,用户态的应用程序也会执行一个操作系统的调用, -检查内核的数据是否准备完成。**如果内核没有准备好数据, -内核会立刻返回结果,用户应用进程不用一直阻塞等待内核准备数据, -而是可以执行其他任务,但仍需要不断的向内核发起系统调用,检测数据是否准备好, -这个过程就叫轮询。** 轮询直到内核准备好数据,然后内核把数据拷贝到用户应用进程, -再进行数据处理。 +在非阻塞IO模型中,用户态的应用程序也会执行一个操作系统的调用,检查内核的数据是否准备完成。**如果内核没有准备好数据, +内核会立刻返回结果,用户应用进程不用一直阻塞等待内核准备数据,而是可以执行其他任务,但仍需要不断的向内核发起系统调用,检测数据是否准备好,这个过程就叫轮询。** 轮询直到内核准备好数据,然后内核把数据拷贝到用户应用进程,再进行数据处理。 ![NIO原理](../../media/pictures/java/linux_io/NIO原理.png) 非阻塞IO的非阻塞体现在: **用户应用进程不用阻塞在对内核的系统调用上** -非阻塞IO的优点在于用户应用进程在轮询阶段可以执行其它任务。 -但这也是它的缺点,轮询就代表着用户应用进程不是时刻都会发起系统调用。 -**可能数据准备好了,而用户应用进程可能等待其它任务执行完毕才会发起系统调用, -这就意味着数据可能会被延时获取。** +非阻塞IO的优点在于用户应用进程在轮询阶段可以执行其它任务。但这也是它的缺点,轮询就代表着用户应用进程不是时刻都会发起系统调用。 +**可能数据准备好了,而用户应用进程可能等待其它任务执行完毕才会发起系统调用,这就意味着数据可能会被延时获取。** #### IO多路复用(网络IO模型) -在IO多路复用模型中,**用户应用进程会调用操作系统的select/poll/epoll函数, -它会使内核同步的轮询指定的socket, -(在NIO中,socket就是注册到Selector上的SocketChannel,可以允许多个) -直至监听的socket有数据可读或可写,select/poll/epoll函数才会返回, -用户应用进程也会阻塞的等待select/poll/epoll函数返回。** -当select/poll/epoll函数返回后,即某个socket有事件发生了,用户应用进程就会 -发起系统调用,处理事件,将socket数据复制到用户进程内,然后进行数据处理。 +在IO多路复用模型中,**用户应用进程会调用操作系统的select/poll/epoll函数,它会使内核同步的轮询指定的socket, +(在NIO中,socket就是注册到Selector上的SocketChannel,可以允许多个)直至监听的socket有数据可读或可写,select/poll/epoll函数才会返回,用户应用进程也会阻塞的等待select/poll/epoll函数返回。** + +当select/poll/epoll函数返回后,即某个socket有事件发生了,用户应用进程就会发起系统调用,处理事件,将socket数据复制到用户进程内,然后进行数据处理。 ![IO多路复用原理](../../media/pictures/java/linux_io/IO多路复用原理.png) @@ -154,44 +131,31 @@ Linux下共有5种IO模型: 2. IO多路复用模型的阻塞体现在: **用户应用进程会阻塞在对select函数上的调用上。** -**IO多路复用的优点在于内核可以处理多个socket, -相当于一个用户进程(线程)就可以处理多个socket连接。** -这样不仅降低了系统的开销,并且对于需要高并发的应用是非常有利的。 -而非阻塞IO和阻塞IO的一个用户应用进程只能处理一个socket, -要想处理多socket,只能新开进程或线程,但这样很消耗系统资源。 +**IO多路复用的优点在于内核可以处理多个socket,相当于一个用户进程(线程)就可以处理多个socket连接。** + +这样不仅降低了系统的开销,并且对于需要高并发的应用是非常有利的。而非阻塞IO和阻塞IO的一个用户应用进程只能处理一个socket,要想处理多socket,只能新开进程或线程,但这样很消耗系统资源。 **PS: -在IO多路复用模型中, socket一般应该为非阻塞的, -这就是Java中NIO被称为非阻塞IO的原因。 -但实际上NIO属于IO多路复用,它是同步阻塞的IO。 -具体原因见 [知乎讨论](https://www.zhihu.com/question/37271342)** +在IO多路复用模型中, socket一般应该为非阻塞的,这就是Java中NIO被称为非阻塞IO的原因。但实际上NIO属于IO多路复用,它是同步阻塞的IO。具体原因见 [知乎讨论](https://www.zhihu.com/question/37271342)** **PS: -select/poll/epoll函数是IO多路复用模型的基础,所以如果想 -深入了解IO多路复用模型,就需要了解这3个函数以及它们的优缺点。** +select/poll/epoll函数是IO多路复用模型的基础,所以如果想深入了解IO多路复用模型,就需要了解这3个函数以及它们的优缺点。** #### 信号驱动IO(网络IO模型) -在信号驱动IO模型中,**用户应用进程发起sigaction系统调用,内核收到并立即返回。 -用户应用进程可以继续执行其他任务,不会阻塞。当内核准备好数据后向用户应用进程 -发送SIGIO信号,应用进程收到信号后,发起系统调用, -将数据从内核拷贝到用户进程,** 然后进行数据处理。 +在信号驱动IO模型中,**用户应用进程发起sigaction系统调用,内核收到并立即返回。用户应用进程可以继续执行其他任务,不会阻塞。当内核准备好数据后向用户应用进程发送SIGIO信号,应用进程收到信号后,发起系统调用,将数据从内核拷贝到用户进程,** 然后进行数据处理。 ![信号驱动IO原理](../../media/pictures/java/linux_io/信号驱动IO原理.png) -个人感觉在内核收到系统调用就立刻返回这一点很像异步IO的方式了,不过 -与异步IO仍有很大差别。 +个人感觉在内核收到系统调用就立刻返回这一点很像异步IO的方式了,不过与异步IO仍有很大差别。 #### 异步IO -在异步IO模型中,**用户进程发起aio_read系统调用,无论内核的数据是否准备好, -都会立即返回。用户应用进程不会阻塞,可以继续执行其他任务。当内核准备好数据, -会直接把数据复制到用户应用进程。最后内核会通知用户应用进程IO完成。** +在异步IO模型中,**用户进程发起aio_read系统调用,无论内核的数据是否准备好,都会立即返回。用户应用进程不会阻塞,可以继续执行其他任务。当内核准备好数据,会直接把数据复制到用户应用进程。最后内核会通知用户应用进程IO完成。** ![异步IO原理](../../media/pictures/java/linux_io/异步IO原理.png) -**异步IO的异步体现在:内核不用等待数据准备好就立刻返回, -所以内核肯定需要在IO完成后通知用户应用进程。** +**异步IO的异步体现在:内核不用等待数据准备好就立刻返回,所以内核肯定需要在IO完成后通知用户应用进程。** ---