美文网首页
操作系统之IO模型

操作系统之IO模型

作者: youzhihua | 来源:发表于2020-06-09 16:55 被阅读0次

一、相关概念

1.1 同步与异步、阻塞与非阻塞

  • 同步和异步:用户程序通过recv()进行系统调用后,如果最后还需要调用read(),则是同步的;否则就是异步的。

  • 阻塞和非阻塞:用户程序通过recv()进行系统调用后,如果还可以做其它事情,则是非阻塞的,反之则是阻塞的。

概念有些抽象,可以通过以下的例子来理解一下这组概念:

假设小明需要在网上下载一个软件:

  • 同步阻塞:如果小明点击下载按钮之后,就一直干瞪着进度条不做其他任何事情直到软件下载完成;
  • 异步阻塞(比较罕见):如果小明点击下载按钮之后,不用瞪着进度条但也不做其他任何事情直到软件下载完成,软件下载完成是会「叮」的一声通知的。
  • 同步非阻塞:如果小明点击下载按钮之后,就去做其他事情了,不过他总需要时不时瞄一眼屏幕看软件是不是下载完成了
  • 异步非阻塞:如果小明点击下载按钮之后,就去做其他事情了,软件下载完之后「叮」的一声通知小明,小明再回来继续处理下载完的软件

1.2 用户态和内核态

1.2.1 用户态和内核态的基本概念

  • 用户态:就是提供应用程序运行的空间,为了使应用程序访问到内核管理的资源例如CPU,内存,I/O。
  • 内核态:控制计算机的硬件资源,例如协调CPU资源,分配内存资源,并且提供稳定的环境供应用程序运行。
用户空间和内核空间

1.2.2 用户态切换到内核态的方式

  • 中断:当外设完成用户的请求时,会向CPU发送中断信号。
  • 异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,就会触发切换。例如:缺页异常。
  • 系统调用:本质上也是中断,属于软中断的一种。

1.3 文件描述符

内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。

二、IO模型

2.1 同步阻塞IO

  • 应用进程向内核发起recfrom读取数据。

  • 准备数据报(应用进程阻塞)。

  • 将数据从内核负责到应用空间。

  • 复制完成后,返回成功提示。

同步阻塞IO

2.2 同步非阻塞IO

  • 应用进程向内核发起recvfrom读取数据。
  • 没有数据报准备好,即刻返回EWOULDBLOCK错误码。
  • 应用进程向内核发起recvfrom读取数据。
  • 已有数据包准备好就进行一下 步骤,否则还是返回错误码。
  • 将数据从内核拷贝到用户空间。
  • 完成后,返回成功提示。
同步非阻塞IO

2.3 IO多路复用

定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力,linux有三种实现方式,分别为select,poll和epoll。

IO多路复用

2.3.1 select

  • 源码

/* According to POSIX.1-2001, POSIX.1-2008 */
    #include <sys/select.h>
    /* According to earlier standards */
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>

    int select(int nfds, fd_set *readfds, fd_set *writefds,
                fd_set *exceptfds, struct timeval *timeout);

    int pselect(int nfds, fd_set *readfds, fd_set *writefds,
                fd_set *exceptfds, const struct timespec *timeout,
                const sigset_t *sigmask);

    void FD_CLR(int fd, fd_set *set);
    int  FD_ISSET(int fd, fd_set *set);
    void FD_SET(int fd, fd_set *set);
    void FD_ZERO(fd_set *set);

select的调用会阻塞到有文件描述符可以进行IO操作或被信号打断或者超时才会返回。

select将监听的文件描述符分为三组,每一组监听不同的需要进行的IO操作。readfds是需要进行读操作的文件描述符,writefds是需要进行写操作的文件描述符,exceptfds是需要进行异常事件处理的文件描述符。这三个参数可以用NULL来表示对应的事件不需要监听。

当select返回时,每组文件描述符会被select过滤,只留下可以进行对应IO操作的文件描述符。

FD_xx系列的函数是用来操作文件描述符组和文件描述符的关系。

FD_ZERO用来清空文件描述符组。每次调用select前都需要清空一次。

select可同时监听的文件描述符数量是通过FS_SETSIZE来限制的,在Linux系统中,该值为1024。

2.3.2 poll

  • 源码
#include <poll.h>

    int poll(struct pollfd *fds, nfds_t nfds, int timeout);

    #include <signal.h>
    #include <poll.h>

    int ppoll(struct pollfd *fds, nfds_t nfds,
            const struct timespec *tmo_p, const sigset_t *sigmask);

    struct pollfd {
        int fd; /* file descriptor */
        short events; /* requested events to watch */
        short revents; /* returned events witnessed */
    };

poll和select用三组文件描述符不同的是,poll只有一个pollfd数组,数组中的每个元素都表示一个需要监听IO操作事件的文件描述符。events参数是我们需要关心的事件,revents是所有内核监测到的事件。

poll在linux下没有监听的文件描述符数量限制,但是如果过多的话,速度也会变慢。

2.3.3 epoll

  • 源码
#include <sys/epoll.h>

    int epoll_create(int size);
    int epoll_create1(int flags);

    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

    int epoll_wait(int epfd, struct epoll_event *events,
                int maxevents, int timeout);
    int epoll_pwait(int epfd, struct epoll_event *events,
                int maxevents, int timeout,
                const sigset_t *sigmask);

epoll_create用于创建一个epoll实例,而epoll_ctl用于往epoll实例中增删改要监测的文件描述符,epoll_wait则用于阻塞的等待可以执行IO操作的文件描述符直到超时。

epoll优于select&poll在下面几点:

  • 在需要同时监听的文件描述符数量增加时,select&poll是O(N)的复杂度,epoll是O(1),在N很小的情况下,差距不会特别大,但如果N很大的前提下,一次O(N)的循环可要比O(1)慢很多,所以高性能的网络服务器都会选择epoll进行IO多路复用。
  • epoll内部用一个文件描述符挂载需要监听的文件描述符,这个epoll的文件描述符可以在多个线程/进程共享,所以epoll的使用场景要比select&poll要多。

2.4 异步IO

进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。  
这个模型工作机制是:告诉内核启动某个操作,并让内核在整个操作(包括第二阶段,即将数据从内核拷贝到进程缓冲区中)完成后通知我们。

异步IO模型

相关文章

  • 操作系统之IO模型

    一、相关概念 1.1 同步与异步、阻塞与非阻塞 同步和异步:用户程序通过recv()进行系统调用后,如果最后还需要...

  • NIO学习笔记

    NIO 操作系统背景知识 unix提供了5中io模型,其中java的底层实现依赖的是操作系统的io复用模型。lin...

  • note

    Java IO,NIO,NIO2 以及与操作系统,磁盘 IO NIO模型selector NIO的核心是IO线程池...

  • Unix五种IO模型

    Unix五种IO模型 IO 是主存和外部设备 ( 硬盘、终端和网络等 ) 拷贝数据的过程。 IO 是操作系统的底层...

  • java基础知识7-IO

    1.IO模型 对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的...

  • 操作系统IO模型(译)

    在学习NIO之前,我们非常有必要了解一下操作系统中的各种IO模型,否则是不会理解NIO的实现的. 这篇文章是我翻译...

  • (转载)【NIO系列】

    原文链接:【NIO系列】——之TCP探秘【NIO系列】——之IO模型 【NIO系列】——之Reactor模型并附上...

  • 0、常见的几种IO模型

    1、操作系统内核 2、BIO模型 BIO(blocking I/O)是阻塞IO模型,每个客户端连接上之后都会启用一...

  • 什么是BIO,NIO与AIO

    计算机中常见的IO模型主要分为几种BIO,NIO和AIO。 操作系统的IO操作包括读写文件,Socket操作等。C...

  • netty源码分析(一)

    nio的源码都是和具体的操作系统底层的io模型有关,都是底层的东西,分析意义不大。linux的底层支持以及几种io...

网友评论

      本文标题:操作系统之IO模型

      本文链接:https://www.haomeiwen.com/subject/jtdrtktx.html