linux IO学习笔记 (持续更新错误)

linux 学习笔记

一、linux的缓存IO机制

从权限上来说,内核拥有权限很高,可访问所有底层硬件。而用户(进程)的权限相对较低,而这样的目的便是为了保护内核的安全。
从内存空间上来说,操作系统把内存分成了两份,一份给内核用(称为内核空间),一份给用户(进程)用(称为用户空间),两者绝对的互不干扰。(windows的蓝屏原因:硬件驱动与系统的不兼容,驱动代码运行在系统内核空间,如果出错就会影响到系统内核,进而系统崩溃,机子死机。而QQ崩溃就不会造成机子死机,因为QQ运行在用户空间)
所以内核的数据与用户的数据不共享,内核如果要把任务(数据)交给用户(进程),就会有一个data copy的过程。

代码获取硬盘文件内数据的过程(IO的一次访问):用户(进程)不具有对硬件(硬盘)的权限,需要申请权限,通过内核来进行系统调用(API)。内核创建 page cache(页缓存)并把用户需要的数据从硬盘一点一点地读取到 page cache中,当把所有数据都准备好后,一次性交给用户进程(这是在缓存非命中的情况下,如果命中缓存则直接返回),于是咱们代码也就读取到了数据,(对比如PHP的 file_get_contents()的一次文件读取过程)。

而写入的流程则是将上面的流程逆着走一遍。远程客户端的数据接收同理,只是读取的起点与写入的终点不同而已。

另,不管代码(用户进程)从哪里 fread 数据,远程客户端数据也好,硬盘数据也好,都得通过一个中间人(内核)来读取(因为没有对硬件的权限)。所以在这个怎么接收数据的问题上产生了难题:如果解决同时接收多个客户端发送来的数据的问题(经典的C10k并发)。于是衍生出了五种IO网络模型:

  • 阻塞 I/O(blocking IO)
  • 非阻塞 I/O(nonblocking IO)
  • I/O 多路复用( IO multiplexing)
    socket的可读可写事件(待整理)
  • 信号驱动 I/O( signal driven IO)
  • 异步 I/O(asynchronous IO)

而基于这5种IO模型,又衍生出很多个服务器模型(IO设计模式),如多进程/线程模型,leader/follower,Reactor,Proactor

二、服务器模型历史

第一阶段:早期服务器模型为一个while死循环,接收一个接连,处理这个连接任务,返回处理结果。全程阻塞,运行中无法处理新的连接。

第二阶段:多进程/线程模型,即为经典的 “connection per process/thread”,一个进程或线程,对应一个连接。这样的话,有多少个进程或线程,就能处理多少个连接请求。

至今:对第二阶段的优化。多进程/线程有很多不足,如资源的拷贝,线程的创建销毁的开销(leader/follower模型,线程池的空闲线程的使用),进程数或线程数上限的问题(限制了连接请求数),单个线程还可以再细化(reactor模型,redis底层采用此模型)等等。以下详细分开记笔记

三、leader-follower多线程模型

线程的三种状态:
1、leader,使命:等待事件任务;特点:始终只有一个leader;状态:等待。
2、processing,使命:处理任务ing;状态:运行中。
3、follower,使命:接收leader 的通知,尝试抢占锁,力图成为leader。状态:空闲。

线程状态转化
1、Leader 等到事件任务时,放出唯一的一把锁,通知followers抢锁(也可能是其它如FIFO的形式选leader或其它策略)。确定某个follower成为leader后,自身转变为 processing 处理任务。
2、processing 处理完任务后,转变为 follower,加入等待队列。

优点:
普通的多线程模型,当主线程接到IO事件时,会创建新的子线程,把要处理的任务数据 copy 交给新的子线程,让它去解决问题,而主线程继续等待请求。子线程处理完任务后,会退出线程并销毁资源。
1、无频繁的子线程创建、销毁的开销
2、无线程间的data copy

四、reactor模型

五、线程池,mysql线程池

阅读参考:
维基百科名称解释
http://rango.swoole.com/archi…

    原文作者:张石磊
    原文地址: https://segmentfault.com/a/1190000016138420
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞