• 【Linux】【网络编程】


    Linux/Unix上的五种IO模型

    参考:https://www.nowcoder.com/study/live/504?&headNav=www

    一, 阻塞/非阻塞、同步/异步

    陈硕:在处理IO时,阻塞和非阻塞是同步IO,只有使用了特殊的API才是异步IO。

    一个典型的网络IO接口调用,分为两个阶段:数据就绪和数据读写。

    数据就绪分为阻塞和非阻塞,表现的结果就是,阻塞当前线程或者是直接返回。
    当阻塞时,函数调用后,如果数据还没有到达,那么就会一直等待直到有数据到达被读取;
    当非阻塞时,函数调用后,会立即返回,根据返回值判断是否成功读取了数据;

    数据读写分为同步和异步。
    同步表示A向B请求调用一个网络IO接口时,数据的读写由请求方A自己完成;
    异步表示A向B请求调用一个网络IO接口时,要向B传入请求的事件及事件发生时通知的方式,A就可以处理其它逻辑了,当B监听到事件处理完成后,用事先约定好的通知方式,通知A处理结果。

    阻塞和非阻塞是在操作系统层面上对TCP接收缓冲区而言的;
    同步异步是对应用程序和内核的交互方式来说的。

    二,Linux、Unix上的五种IO模型

    2.1 阻塞 blocking

    阻塞blocking:调用者调用了某个IO函数,等待函数返回,期间什么也做不了,不停的检查这个函数有没有问题,必须等这个函数但会才进行下一步动作。

    在这里插入图片描述

    2.2 非阻塞 non-blocking(NIO)

    在Linux、Unix中将文件描述符设置为非阻塞(fcntl())。

    非阻塞等待,每隔一段时间就检测IO事件是否就绪,没有就可以做其他事,非阻塞I/O执行系统调用总是立即返回,不管事件是否已经发生。

    若事件没有发生,则返回-1,此时可以根据errno区分这两种情况,对于acceptrecvsend,事件未发生时,errno通常被设置未EAGAIN

    在这里插入图片描述

    2.3 IO复用 IO multiplexing

    Linux用select/poll/epoll函数实现IO复用模型,这些函数会使进程阻塞,但是和阻塞IO不同的是这些函数可以同时阻塞多个IO操作,而且可以同时对多个读操作、写操作的IO函数进行检测,直到有数据可读或可写时,才真正调用IO操作函数。

    在这里插入图片描述

    2.4 信号驱动 signal-driven

    Linux用套接口进行信号驱动IO,安装一个信号处理函数,进程继续运行并不阻塞,当IO事件就绪,进程收到SIGIO信号,然后处理IO事件。

    在这里插入图片描述

    内核在第一个阶段是异步,在第二个阶段是同步;与非阻塞IO的区别在于它提供了消息通知机制,不需要用户进程不断的检查,减少了系统API的调用次数,提高了效率。

    2.5 异步IO asynchronous

    Linux中,可以调用alo_read/alo_write函数告诉内核描述字缓冲区指针和缓冲区大小、文件偏移及通知方式然后立即返回,当内核将数据拷贝到缓冲区后,再通知应用程序。

    异步IO使用比较少。

    在这里插入图片描述

    异步IO中包含了一个结构体aiocb,该结构体包含的成员如下:

    struct aiocb
    {
    	int aio_fildes;  // file descriptor
    	int aio_lio_opcode;  // operation to be performed
    	int aio_reqprio;  // request priority offset
    	volatile void *aio_buf;  // location of buffer
    	size_t aio_nbytes;  // length of transfer
    	struct sigevent aio_sigevent;  // signal number and value
    	
    	struct aiocb *__next_prio;
    	int __abs_prio;
    	int __policy;
    	int __error_code;
    	__ssize_t __return_value;
    	
    #ifndef __USE_FILE_OFFSET64
    	__off_t aio_offset;  // file offset
    	char __pad[sizeof(__off64_t) - sizeof(__off_t)];
    #else
    	__off64_t aio_offset;  // file offset
    #endif
    char __glibc_reserved[32];
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    TCP到底有多厉害?
    Spring5源码11-容器刷新refresh方法(注解版)
    常见ai智能机器人呼叫中心等如何让短信营销更加有价值?
    BPF 调度器 sched_ext 实现机制、调度流程及样例
    Oracle19c安装报错,如何解决?
    【Vue 基础知识】控制元素显示隐藏的方法和区别
    【算法】滑动窗口题单——2.不定长滑动窗口(求最长/最大)
    Vue3 从入门到放弃 (第六篇.插槽(Slot)的使用)
    [微前端实战]---03微前端实现方式对比
    abp(net core)+easyui+efcore实现仓储管理系统——供应商管理升级之下(六十四)
  • 原文地址:https://blog.csdn.net/sinat_41752325/article/details/127722397