unix/linux下几种常见的IO模型

Unix/Linux 编程:网络编程之 IO模型 一、阻塞IO(blocking) 主线程阻塞等待用户连接请求(accept阻塞)。等请求达到以后再调用(recv)系统调用接收数据,这时候又阻塞等待。 等内核将数据接受好并从内核空间拷贝到用户空间后,系统调用返回,表明数据读取完毕。 这个操作在等待IO的时候会将主线程挂起而不能执行其他操作,浪费了大量服务器性能。 二、多线程(blocking+multithread) 由于accept系统调用会对每个客户端的连接都返回一个fd,因此可以利用多线程的方法。主线程只负责accept处理连接请求。 阅读详情

unix/linux下几种常见的I/O模型:

(以下图片均引用自UNP一书)

阻塞式I/O:

顾名思义就是当进行I/O时,数据还没有准备好,就会阻塞在I/O上。
这里写图片描述
下面配合代码进行讲解:

#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>

#define SERV_PORT 8000

int main(void)
{
  struct sockaddr_in serv_addr, clie_addr;
  socklen_t clie_addr_len;
  int sockfd;
  char buf[BUFSIZ];
  char str[INET_ADDRSTRLEN];
  int i, n;

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  bzero(&serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(SERV_PORT);

  bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

  printf("Accepting connections ...\n");
  while (1)
  {
      clie_addr_len = sizeof(clie_addr);
      //当客户端没发送数据时,会一直阻塞
      n = recvfrom(sockfd, buf, BUFSIZ,0, (struct sockaddr *)&clie_addr, &clie_addr_len);
      if (n == -1)
        perror("recvfrom error");

      printf("received from %s at PORT %d\n",
            inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
            ntohs(clie_addr.sin_port));
      n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clie_addr, sizeof(clie_addr));
      if (n == -1)
        perror("sendto error");
  }
  close(sockfd);
  return 0;
}

当运行到recvfrom时,如果客户端的数据还未发过来,则程序就阻塞在recvfrom上,等数据到了之后内核将数据拷贝给用户的缓冲区中或者因为某些原因调用失败了才会返回,中间的过程是一直阻塞在recvform函数上的。这种I/O方式就称为阻塞式I/O模型。

非阻塞I/O模型:

这里写图片描述

#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#define SERV_PORT 8000

int main(void)
{
  struct sockaddr_in serv_addr, clie_addr;
  socklen_t clie_addr_len;
  int sockfd;
  char buf[BUFSIZ];
  char str[INET_ADDRSTRLEN];
  int i, n;

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  bzero(&serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(SERV_PORT);

  bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

  //设置非阻塞
  int flag = fcntl(sockfd, F_GETFL);
  flag |= O_NONBLOCK;
  fcntl(sockfd, F_SETFL, flag);
  printf("Accepting connections ...\n");
  while (1)
  {
      clie_addr_len = sizeof(clie_addr);
      //由于我们对sockfd文件描述符设置了非阻塞,所以recvfrom调用会一直返回-1并设置errno为EAGAIN直到接收到数据
      n = recvfrom(sockfd, buf, BUFSIZ,0, (struct sockaddr *)&clie_addr, &clie_addr_len);
      if (n == -1 && errno == EAGAIN)
        perror("recvfrom error");

      printf("received from %s at PORT %d\n",
            inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
            ntohs(clie_addr.sin_port));
      n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clie_addr, sizeof(clie_addr));
      if (n == -1)
        perror("sendto error");
  }
  close(sockfd);
  return 0;
}

设置了文件描述符为非阻塞态之后,recvfrom就不会等待数据到达了,而是直接返回。所以当我们采用非阻塞I/O模型时,需要轮询内核,查看数据是否准备就绪。这样的做法会耗费大量的cpu资源,因为每次都要在内核和用户态之间切换。

I/O复用模型:

select、poll、epoll都属于I/O复用模型。当系统调用这几个系统调用时,会阻塞在这几个系统调用上,但不是阻塞在真正的I/O系统调用上。这样做的好处是可以一次性监控多个文件描述符,而不用像阻塞I/O模型那样每次只处理一个文件描述符。
这里写图片描述
这里只贴出select的server端代码以供讲解:

#include <iostream>
using namespace std;
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MAXLINE 80
#define SERV_PORT 6666

int main(int argc, char *argv[])
{
    int i, max_i, max_fd, listen_fd,
    conn_fd, sock_fd;
    //用一个client数组专门来存放就绪的描述符
    int nready, client[FD_SETSIZE];
    ssize_t n;
    fd_set rset, allset;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    socklen_t cliaddr_len;
    struct sockaddr_in cliaddr, servaddr;


    listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    listen(listen_fd, 20);

    //记录监控的最大的文件描述符
    max_fd = listen_fd;
    //max_i用来记录client数组的有效下标
    max_i = -1;

    //初始化client数组
    for(i = 0; i < FD_SETSIZE; i++)
    {
        client[i] = -1;
    }

    //初始化文件描述符集合
    FD_ZERO(&allset);
    FD_SET(listen_fd, &allset);

    while(1)
    {
        //allset用来存放需要监听的所有文件描述符集合,而rset是指就绪的文件描述符集合
        rset = allset;
       //阻塞等待可读的文件描述符,如果有,则立即返回,否则阻塞
        nready = select(max_fd + 1, &rset, NULL, NULL, NULL);
        if(nready < 0)
        {
            perror("select error");
            exit(1);
        }
        //如果建立socket连接的描述符处于就绪
        if(FD_ISSET(listen_fd, &rset))
        {
            cliaddr_len = sizeof(cliaddr);
            conn_fd = accept(listen_fd, (struct sockaddr *)&cliaddr, &cliaddr_len);
            printf("received from %s at PORT %d\n",
                    inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                    ntohs(cliaddr.sin_port));
            for(i = 0; i < FD_SETSIZE; i++)
            {
                if(client[i] < 0)
                {
                    client[i] = conn_fd;
                    break;
                }
            }
            if(i == FD_SETSIZE)
            {
                fputs("too many clients\n", stderr);
                exit(1);
            }
            //将新的描述符加入监听的文件描述符集合中
            FD_SET(conn_fd, &allset);
            //更新最大的文件描述符和最大下标
            if(conn_fd > max_fd)
            {
                max_fd = conn_fd;
            }
            if(i > max_i)
            {
                max_i = i;
            }
            //如果没有就绪的文件描述符就退出本次循环,重新调用select监听
            if(--nready == 0)
            {
                continue;
            }
        }

        //轮询找到就绪的文件描述符
        for(i = 0; i <= max_i; i++)
        {
            if((sock_fd = client[i]) < 0)
            {
                continue;
            }
            if(FD_ISSET(sock_fd, &rset))
            {
                if((n = read(sock_fd, buf, MAXLINE)) == 0)
                {
                    close(sock_fd);
                    FD_CLR(sock_fd, &rset);
                    client[i] = -1;
                }
                else
                {
                    int j;
                    for(j = 0; j < n; j++)
                        buf[j] = toupper(buf[j]);
                    write(sock_fd, buf, n);
                }
                if(--nready == 0)
                {
                    break;
                }
            }
        }
    }
    close(listen_fd);
    return 0;
}

可以看到,select一次可以处理多个就绪的文件描述符,I/O复用模型就是这样的一个特点。效率方面比前几种都要好的多。而epoll则是poll的加强版,select和poll都是采用轮询查看哪个文件描述符就绪,而epoll是采用的回调机制来激活文件描述符,将就绪的文件描述符加入链表中,返回时,就知道了具体是哪些文件描述符处于就绪中。

信号驱动式I/O模型:

信号驱动这种方式的意思就是我们事先调用sigaction函数捕捉SIGIO信号并定义处理函数,等到数据已经准备就绪时,内核就发送SIGIO信号,当前进程就可以执行SIGIO处理函数了,在处理函数中调用recvfrom读取数据即可。
这种I/O模型的优点是当进程调用recvfrom时,数据必定已经可以读取了,因为当内核发送SIGIO信号时,数据已经准备就绪了。所以我们可以执行其它代码,而不用阻塞在某一处了。
这里写图片描述

异步I/O模型:

前面的I/O模型都是需要我们在读写事件就绪后自己负责进行读写,而异步I/O则不需要,是内核替我们做了这些事,最后只需要当I/O完成时才通知我们。注意它和信号驱动式I/O的不同,信号驱动式I/O是通知我们何时可以进行I/O,而异步I/O是通知我们何时完成了I/O。
这里写图片描述

最后贴上阻塞式I/O和非阻塞式I/O用于测试的client端代码:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>

#define SERV_PORT 8000

int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    int sockfd, n;
    char buf[BUFSIZ];

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    servaddr.sin_port = htons(SERV_PORT);

    while (fgets(buf, BUFSIZ, stdin) != NULL) {
        n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
        if (n == -1)
            perror("sendto error");

        n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0);         //NULL:不关心对端信息
        if (n == -1)
            perror("recvfrom error");

        write(STDOUT_FILENO, buf, n);
    }

    close(sockfd);

    return 0;
}

测试I/O复用的话,直接使用nc 127.0.0.1 6666来模拟client端即可。

法兰克仿真软件FANUC CNC Guide v25.0 安装教程及中文设置 下载地址在文末。我们公司用新到一批FANUC 系统的设备,为方便使用就装了一个 FANUC 数控系统仿真软件FANUC CNC Guide v25.0 ,还是最新版不是市面上流传的老版本。模拟学习一下。 阅读详情

相关推荐

配置Dot1q终结子接口实现跨设备VLAN间通信示例

示例图 一.实验目的 1.配置Dot1q终结子接口实现跨设备VLAN间通信示例 二.注意事项 1.Dot1q终结子接口和QinQ终结子接口不支持透传不带VLAN Tag的报文, 收到不带VLAN Tag的报文会直接丢弃 2.由于三层以太网子接口不支持VLAN报文,当它收到VLAN报文时,会将VLAN报文当成是 非法报文而丢弃,因此,需要在子接口上将VLAN Tag剥掉,也就是需要VLAN终结 三.VLAN终结简介 1.VLAN终结的实质包含两个方面: ①.对接口接收到报文,剥除VLAN标

qq_44751470的博客 7097

Linux中5种IO模型

同步/异步,阻塞/非阻塞,Linux中5种IO模型,BIO、NIO、AIO

weixin_45819295的博客 2804

UG476 GT Transceivers文档翻译和自身理解

对UG476 Xilinx官方文档进行翻译的基础上加上自己的理解

weixin_45143788的博客 4598

Linux的五个I/O模型

前面的 fcntl()函数解决了文件的共享问题, 接下来该处理 I/O 复用的情况了。 总的来说, I/O 处理的模型有 5 种。  1.阻塞 I/O 模型: 在这种模型下, 若所调用的 I/O 函数没有完成相关的功能, 则会使进程挂起, 直到相关数据到达才会返回。 如常见对管道设备、 终端设备和网络设备进行读写时经常会出现这种情况。 2.非阻塞 I/O 模型: 在这种模型下, ...

QtHalcon 5476

simulink中MIL测试简单理解

输入信号设置如下:选中New Test Case1 ---INPUT。5、新建(选择New,Test from Spreadsheet)6、可以新建也可以导入(Use existing test)Source:Output为自己预测结果。3、右键子系统(Create)打开生成表格,可以自己调试。4、创建测试用例表格。保存路径为模型路径。保存路径在模型路径。8、运行测试设h置。

lingdianhuat的博客 1784

告别糊涂账!用CKM3底表逻辑自建物料成本监控报表(含ABAP代码片段)

本文详细介绍了如何利用CKM3底表逻辑自建物料成本监控报表,解决标准报表无法穿透成本差异根源的问题。通过ABAP代码片段和四步架构法,帮助财务团队精准分析成本构成,优化成本核算批量处理,实现多维透视差异分析,提升成本监控效率。

weixin_30740295的博客 267

Linux下五种IO模型

目录1、引入的概念1.1 用户空间和内核空间1.2 进程切换1.3 进程的阻塞 1.4文件描述符fd1.5 缓存IO2、Linux IO模型2.1 同步阻塞IO(blocking IO)2.1.1 同步阻塞情景描述:2.1.2 网络模型2.1.3 流程描述2.2 同步非阻塞IO(nonlocking IO)2.2.1 同步非阻塞情景描述2.2.2 网络模型2.2.3 流程描述2.3 IO多路复用(IO multiplexing)2.3.1 IO多路复用情景描述2.3.2 网络模型2.3.3 流程描述2.4

m0_52165864的博客 1719

FPGA时序约束--实战篇(读懂Vivado时序报告)

本文将详细介绍如何读懂Vivado时序报告,包括报告的基本结构和如何分析报告。

mengzaishenqiu的博客 1万+

Linux系统--五种IO模型

Linux中的五种IO模型主要包括阻塞IO、非阻塞IO、IO复用、信号驱动IO和异步IO。

积木的笔记 1447

硅谷刷屏的ClawdBot,让Mac mini卖爆了!创始人爆料:一人开发、100% AI 写代码

这两天,个人 AI 助手 ClawdBot 席卷硅谷,国内外社交平台上全是关于它的讨论。 在试用后,网友们纷纷给出了很高的评价。“它是迄今为止最伟大的 AI 应用,相当于你 24 小时全天候专属 AI 员工。”Creator Buddy 创始人兼 CEO Alex Finn 盛赞道,“这就是他们 (Anthropic) 希望 Claude Cowork 呈现的样子。”

技术引领业务创新 1584

【2005】人工智能⭐

问题的解答来自于过去的经验而不是规则,这些经验是以案例方式存储的。但是当人们遇到一个新的问题的时候,一般先是回忆,从记忆中找到一个与新的问题相似的案例,然后把该案例的有关信息和知识复用到新问题的求解之中。1、若案例(case)不够充足,而有足够的规则(知识),试问如何构建一个包含有基于案例推理和基于规则推理的推理系统,以使推理效率提高而且总能求得问题的解。一般认为,CBR适合缺乏完备和健全的理论,但又可获取丰富经验的领域,而RBR则适合于对领域有充分的认识,能以完备和健全的形式表示领域理论的场合。

super_mochi1 280

Linux中的五种IO模型

Linux中有以下五种IO模型。一、同步阻塞IO(Blocking IO, BIO)二、同步非阻塞IO(Non-Blocking IO, NIO)三、IO多路复用 四、信号驱动 I/O 五、异步 I/O(Async IO, AIO)

m0_56602092的博客 728

2024年11月架构设计师案例分析真题回顾,附参考答案、解析及所涉知识点(一)

软考高级系统架构设计师考试包含三个科目:信息系统综合知识、案例分析和系统架构设计论文。考试形式为机考。本文主要回顾2024年下半年(2024-11-10)系统架构设计师考试上午第二科案例分析的题目,同时附带参考解答、解析和所涉知识点。

一几文的编程学习笔记。 2418

Linux/Unix五种IO模型

五种IO模型 在《Unix网络编程》一书中提到了五种IO模型,分别是:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。也被称为Linux的五种网络IO模型。 由于服务器端一般都是使用的Linux操作系统,所以了解这几种io模型学习java网络io模型的基础。Java的IO模型与Unix的IO模型的对应关系(这个对应关系并不严格):java-BIO模型对应Unix阻塞IO, java-NIO对应IO多路复用,java-AIO对应异步IO。 ............

m0_45861545的博客 1823

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【Linux C | I/O模型】Unix / Linux系统的5种IO模型 | 图文详解

本文图文详解Linux系统的五种IO模型,阻塞I/O模型、非阻塞I/O模型、复用式I/O模型、信号驱动式I/O模型、异步I/O模型

wkd_007的博客 2191

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

(通俗易懂)Unix/Linux上的五种IO模型

通俗易懂系列第二节,Unix/Linux上的五种IO模型

weixin_45634782的博客 984

Linux/Unix常见IO模型

应用进程向内核发起 I/O 请求后不再会同步等待结果,而是会立即返回,通过轮询的方式获取请求结果。NIO 相比 BIO 虽然大幅提升了性能,但是轮询过程中大量的系统调用导致上下文切换开销很大。所以,单独使用非阻塞 I/O 时效率并不高,而且随着并发量的提升,非阻塞 I/O 会存在严重的性能浪费。

MrLee的博客 1109

Unix网络编程里面定义的几种IO模型

I/O(英语:Input/Output),即输入/输出,通常指数据在存储器(内部和外部)或其他周边设备之间的输入和输出,是信息处理系统(例如计算机)与外部世界(可能是人类或另一信息处理系统)之间的通信。输入是系统接收的信号或数据,输出则是从其发送的信号或数据。 Unix网络编程中的五种IO模型 blocking IO - 阻塞IO nonblocking IO - 非阻塞IO IO multiplexing - IO多路复用 asynchronous IO - 异步IO signal driven I.

githubcurry,985cs博士在读 520

Unix网络 IO 模型及 Linux 的 IO 多路复用模型详解

本文主要探讨的问题有以下两个: Unix 中的五种网络 IO 模型; Linux 中 IO 多路复用的实现。 一、基本概念 在介绍网络模型之前,先简单介绍一些基本概念。 1.文件描述符 fd 文件描述符(file descriptor,简称 fd)在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。...

zhipingxi的博客 421

5.2、Unix/Linux上的五种IO模型

5.2、Unix/Linux上的五种IO模型1.阻塞blocking2.非阻塞non-blocking(NIO)3.IO复用(IO_multiplexing)4.信号驱动(signal-driven)5.异步(asynchronous)①异步函数介绍 1.阻塞blocking 调用者调用了某个函数,等待这个函数返回,期间什么也不做,不停的去检查这个函数有没有返回,必 须等这个函数返回才能进行下一步动作。 2.非阻塞non-blocking(NIO) 非阻塞等待,每隔一段时间就去检测IO事件是否就绪。

z2812470857的博客 1074

Unix 网络 IO 模型及 Linux 的 IO 多路复用模型

本文主要探讨的问题有以下两个: Unix 中的五种网络 IO 模型; Linux 中 IO 多路复用的实现。 基本概念 在介绍网络模型之前,先简单介绍一些基本概念。 文件描述符 fd 文件描述符(file descriptor,简称 fd)在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向...

yangrendong的专栏 389

网络编程2: Unix/Linux下的五种IO模型

Unix/Linux下的五种IO模型(网络编程的角度)

yubaoaihh 299

unix和Linux的五种io模型,Unix的五种IO模型介绍

前言之前打算总结一下Java的BIO(IO),AIO,NIO,最后一步步深入,发现Unix(Linux)的IO模型需要提前掌握,所以先总结一下Unix的IO模型。概述Java IO 与 Unix IO 的关系(非严格对应)Unix网络编程中介绍了五种IO模型,分别是:阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO。Java的IO模型与Unix的IO模型的对应关系如下所示(这个对应关系并...

weixin_28973627的博客 276

Unix网络编程之5种IO模型

1. Unix/Linux操作系统简述 Unix操作与Linux系统结构图解 (引用计算机操作系统书籍) 概要说明 用户空间: 姑且将上述用户级别或者是unix编程的应用程序的部分称为用户空间,我们可以通过启动进程来调用内核来完成从硬件设备读取或写入等操作 系统内核: 是直接与计算机硬件打交道的应用程序级别,在计算机相关的书籍中也称为操作系统,可以通过操作系统级别提供的一些组件来帮助...

疾风先生的博客 687

【Linux网络】五种IO模型与非阻塞IO

本文聚焦操作系统与 Linux 网络编程核心 IO 体系,从 IO 最底层的本质概念入手,拆解 IO 执行的两大核心步骤,解释 IO 运行低效的根本原因,并给出优化 IO 效率的核心思路。为了降低抽象概念的理解难度,全文采用钓鱼生活化案例类比业界通用的五种经典 IO 模型,依次讲解阻塞 IO、非阻塞 IO、信号驱动 IO、IO 多路复用、异步 IO 的运行逻辑,同时精准界定同步 IO 与异步 IO的判定标准,搭配可直接编译运行的 C 语言代码完成信号驱动 IO、POSIX 异步 IO 的实操演示。

艾莉丝努力练剑的博客,感谢大家一直以来的对艾莉丝的支持和鼓励,uu们如果对C/C++方向感兴趣的话,可以通过艾莉丝主页的微信名片加艾莉丝的好友,和努力练剑的艾莉丝一起加油! 2697

常见Linux IO模型分析

LINUX常见IO模型介绍 UNIX中常见IO模型有五种:阻塞 IO、非阻塞IO、多路复用IO、异步IO、信号驱动IO。其中阻塞IO、非阻塞IO、多路复用IO、信号驱动IO都属于同步IO。 同步IO和异步IO 同步IO:应用程序主动向内核查询是否有可用数据,如果有自己负责把数据从内核copy到用户空间。 异步IO:应用程序向内核发起读数据请求需要:(1)告诉内核数据存放位置(2

lovelinx的专栏 526

Linux IO 模型纵深解析 01:从 Unix 传统到 Linux 内核的 IO 第一性原理

本文围绕 Linux IO 中最容易被混淆的概念——阻塞 / 非阻塞、同步 / 异步,给出一套可验证的语义坐标系。通过“线程是否被挂起”与“IO 完成责任在谁”两个正交维度,澄清常见误解,解释为何同步 API 不必然阻塞、非阻塞也不等于异步。文章结合 read/write、O_NONBLOCK 与等待语义,揭示 Linux 文件 IO 异步化受限的深层原因,并为理解后续的阻塞机制、多路复用与 io_uring 奠定统一认知基础。

a1933580388的博客 988
上一篇: atom安装markdown-preview-enhanced和markdown-pdf插件
下一篇: epoll比select和poll高效的原因
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值