网络编程IO

article/2025/9/22 7:47:42

文章目录

  • 前言
  • 用户空间和内核空间
  • 系统调用
  • 一、同步IO模型
    • 1、阻塞式IO模型
    • 2、非阻塞式IO模型
    • 3、IO复用模型
    • 4、信号驱动IO模型
  • 二、异步IO模型
  • 三、同步和异步


前言

IO操作由两个部分组成:发起IO请求、实际进行IO操作。
也就是下图所示的等待数据从磁盘拷贝到内核空间将数据从内核复制到用户空间两部分。


用户空间和内核空间

IO操作涉及了磁盘或网卡,也就是计算机硬件方面。为了限制应用随意访问硬件而导致系统崩溃,所以区分出了用户空间和内核空间这两个概念。用户空间和内核空间共同组成了一块寻址空间(也称为虚拟空间)映射到不同的物理内存,在32位机器上占4GB,64位机器上占8GB。其中用户空间在32位机器上占据低位的3GB,内核空间占据高位的1GB
内核态和用户态
进程运行在用户空间称为用户态,运行在内核空间称为内核态。

系统调用

应用请求传给内核,调用相应的内核函数来完成所需的处理,将处理结果返回给应用程序。系统调用工作在内核态,实际上,系统调用是用户空间访问内核空间的唯一手段(除异常和陷入外,它们是内核唯一的合法入口)。在这里插入图片描述

一、同步IO模型

同步IO:IO的读写操作是在IO事件发生之后,由应用进程执行

1、阻塞式IO模型

阻塞IO是发起IO请求是阻塞,进行实际IO操作也阻塞。
在这里插入图片描述

先解释一下阻塞的概念:阻塞是进程自身的一直主动行为,且只有处在运行态的进程才可能进入阻塞状态,当进入阻塞时,进程不占系统资源(有种拿时间换空间的思想)。简言之,阻塞就是一直在等待且不占用CPU资源。

数据从磁盘拷贝到内核缓冲区,再从内核缓冲区拷贝到用户空间缓冲区。在这段时间内,进程是一直处于阻塞状态的,全部拷贝完后,进程才解除阻塞状态。

基本IO操作默认为阻塞

输入操作,包括read、readv、recv、recvfrom、recvmsg.

当执行这些函数对一个套接字进行读操作时,若该套接字的输入缓冲区无数据可读,则调用该函数的进程则会进入阻塞状态,直到有数据到达。

输出操作,包括write、writev、send、sengto、sendmsg

内核从应用进程(用户空间)的缓冲区复制数据到该套接字的输出缓冲区,如果输出缓冲区中没有足够的空间,进程将被阻塞,直到有空间为止。

2、非阻塞式IO模型

非阻塞IO是发起IO请求时不阻塞,进行实际IO操作是阻塞。
在这里插入图片描述

针对非阻塞IO执行的系统调用总是立即返回的,若事件未发生则返回-1和出错结果一样,所以要通过errno来判断;

实现非阻塞IO有几种办法
1、通过open打开文件描述符,指定O_NONBLOCK标志
2、对于一个打开了的文件描述符,则可调用fcntl函数。
3、给socket系统调用向其第二个参数传递SOCK_NONBLOCK
代码如下(示例):

....
//以非阻塞读写打开这个文件
open("/tmp/out",O_RDWR|O_NONBLOCK)//把sockfd设置成非阻塞
fcntl(sockfd, F_SETFL, O_NONBLOCK);socket(PF_INET,SOCK_STREAM|SOCK_NONBLOCK,0);
....

很显然当事件发生时调用非阻塞IO能够提高程序的效率,因此非阻塞IO一般和其他IO通知机制一起使用,例如IO复用技术。

3、IO复用模型

IO复用也是同步IO的一种
利用单个线程来监听多个文件描述符fd,在某个fd可读、可写时获得通知,从而避免无效等待,提升 CPU利用率
在这里插入图片描述

从上图看出,和阻塞IO的模型好像大同小异,但是它能提高程序的效率就是因为能够同时监视多个文件描述符事件的发生,而IO阻塞模型是针对于单事件的。

linux中IO复用包括select、poll、epoll
区别:
select和poll只会通知有fd已就绪,但不会具体通知是哪个fd,因此需要遍历所有的fd来确认;
epoll则会在通知有fd就绪时,把具体的fd告诉应用进程;

select模式存在的问题:
1、需要将整个fd_set拷贝到内核空间,select返回后还要再次拷贝fd_set回用户空间
2、select无法得知具体是哪个fd就绪,要遍历整个fd_set
3、最多只能同时监听1024个fd

poll模式相较于select模式的改进
fd的数量无上限,因为采用的是链表存储

epoll是select和poll的改进
1、epoll_create
内核空间创建一个epoll例程(用来保存注册监听事件的文件描述符的空间),创建例程的同时创建了红黑树和链表,创建完成后返回一个epfd,epfd是epoll例程的唯一标识。红黑树存放要监听的fd,链表存放已就绪的fd。

2、epoll_ctl
生成epoll例程后,在红黑树上对fd进行增删改查

#include <sys/epoll.h>
epoll_ctl(int epfd,int op,int fd,struct epoll_event *event)
--epfd就是epoll_create的返回值
--op是用于指定监视对象的操作(增删改)EPOLL_CTL_ADDEPOLL_CTL_MODEPOLL_CTL_DEL
--fd就是文件描述符
--event是监视对象的事件类型,常用的有EPOLLINEPOLLOUTEPOLLONESHOT:一个线程读取某个socket上的数据后开始处理数据,在处理过程中该socket上又有新数据可读,此时另一个线程被唤醒读取,此时出现两个线程处理同一个socket
我们期望的是一个socket连接在任一时刻都只被一个线程处理,通过epoll_ctl对该文件描述符注册epolloneshot事件,
一个线程处理socket时,其他线程将无法处理,当该线程处理完后,需要通过epoll_ctl重置epolloneshot事件
/*举个例子*/
struct epoll_event ev;/*event是一个结构体数组*/
ev.data.fd=sockfd;
ev.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&ev);

3、epoll_wait
监听来自epfd中红黑树上的文件描述符,当有就绪的fd将其添加到链表中,再拷贝到events中

int epoll_wait(int epfd,struct epoll_event *events,int MaxEvents,int timeout);
--epfd
--events 用于保存发生(读写)事件的文件描述符集合的结构体地址
--MaxEvents 可以保存的最大事件数
--timeout 超时设置,一般习惯设置-1,一直等待直到发生事件
--成功则返回发生事件的文件描述的个数,失败返回-1
/*举个例子*/
#define MaxEvents	200
struct epoll_event events[MaxEvents];
epoll_wait(epfd,events,MaxEvents,-1);

epoll模式

LT(Level Trigger)

LT也就是水平触发(条件触发),Epoll的默认工作模式。 当fd有数据可读时会重复通知多次,直至数据处理完成(fd依然存在链表中)

假如服务器端输入缓冲接收到50字节数据时,这时操作系统将通知该事件(注册了的文件描述符)。这时服务器读了20字节还剩30字节的情况下,仍然会注册事件,会多次调用epoll_wait()。简言之,只要输入缓冲存在数据则会一直注册事件。

LT模式是高电平触发的,也就是说当输入缓冲区不为空是返回EPOLLIN,代表有数据可读,当输出缓冲区不满返回EPOLLOUT,能够从应用进程拷贝数据到输出缓冲区。
ET(Edge Trigeer)

ET是边缘触发(电平触发)。当fd有数据可读时,只会被通知一次,不管数据是否被处理完成(fd直接从链表中删除)

ET相比较LT的优点:
虽然ET实现复杂但避免了LT模式可能出现的惊群问题:当一个fd的事件被触发时,所有等待这个fd的线程或进程都被唤醒。

有两种方式能够解决ET的问题:
1、处理没读完的fd时,应该主动调用EPOLL_CTL把fd的属性改为EPOLLIN,这样下次调用EPOLL_WAIT时还是会通知你该fd可读;
2、除此之外应该把输入缓冲中的内容全部读取,通过循环调用read函数来实现。这里应该要使用非阻塞IO,如果使用阻塞IO即使把数据全部读取出来,也会阻塞等待下一次数据的到来,所以要通过使用fcntl函数来给套接字加上O_NONBLOCK。

ET模式是电平触发,由高电平->低电平||低电平->高电平时会发生IO事件。也就是缓冲区的状态发生变化时才会触发。

events.event=EPOLLIN|EPOLLET;/*将要监视的事件注册为ET*/
int flag=fcntl(fd,F_GETFL,0);/*为了保存之前的状态*/
fcntl(fd,F_SETFL,flag|O_NONBLOCK);/*设置套接字状态*/

输入缓冲区为空 低电平,不空高电平 。
输出缓冲区不满 高电平,满低电平。

应用场景
当所有的fd都是活跃连接,使用epoll,需要建立文件系统,红黑书和链表对于此来说,效率反而不高,不如selece和poll

当监测的fd数目非常大,成千上万,且单位时间只有其中的一部分fd处于就绪状态,这个时候使用epoll能够明显提升性能

4、信号驱动IO模型

信号驱动IO是与内核建立SIGIO的信号关联并设置回调,当内核fd就绪时,会发出SIGIO信号通知用户,期间用户进程不阻塞在这里插入图片描述

信号驱动IO的缺点:
当有大量IO操作时,会有很多信号,SIGIO的信号处理函数可能会来不及处理,从而丢失信号;
内核空间和用户空间的信号交互也会使得性能低。

二、异步IO模型

异步IO是实际进行IO操作时进程没有被阻塞,也就是内核帮你完成实际IO操作,完成后把结果返回给你。发起IO请求同样不阻塞。
在这里插入图片描述

POSIX的异步IO函数以aio_或lio_开头,给内核传递fd、缓冲区地址、缓冲区大小以及文件偏移(与lseek类似),并告诉内核当整个操作完成后通知我们的方式。调用这类函数时会立即返回,并且在等待IO完成期间,进程不会被阻塞。

异步IO的缺点:
在使用时需要控制好并发量,因为用户空间只管向内核空间扔IO请求就行,高并发的情况下会使得内核空间崩溃。因为要加上各种因素的控制代码量也会复杂,所以使用的少。

三、同步和异步

同步和异步区分的是内核向进程通知的是何种IO事件(就绪or完成),以及是有谁来完成IO事件(进程or内核)。
在这里插入图片描述

并发模式中,同步指的是程序按照代码从上到下依次执行;异步是程序的执行需要事件来驱动(信号、中断)。
在这里插入图片描述


http://chatgpt.dhexx.cn/article/vPuFn5rn.shtml

相关文章

Linux 下文件IO编程进程控制实验

Linux 下文件IO编程&进程控制实验 一、基本I/O操作 (1).Linux的输入/输出&#xff08;I/O&#xff09;操作&#xff0c;通常为五个方面&#xff1a;打开&#xff0c;读取&#xff0c;写入&#xff0c;定位和关闭&#xff1b;对应的函数分别为&#xff1a;open&#xff08;…

文件IO(IO编程)

一、文件IO&#xff08;IO编程&#xff09; 系统IO&#xff1a;和系统有关的IO接口函数 标准IO: 标准库里面的IO接口函数 #include <stdio.h> 目录操作&#xff1a;操作目录相关的IO接口函数 LCD屏的操作&#xff1a;刷图 TS(touch screen)触摸屏的操作:点击、滑动 二、…

I/O编程

一、标准IO 1.1、概述 标准IO 是ANSI C提供的函数接口&#xff0c;在文件IO的基础上封装出来的。任何兼容标准C库的操作系统都可以使用接口&#xff0c;具有更好的移植性。标准IO在执行时也会用到系统调用&#xff0c;为了增加内核的工作效率&#xff0c;减少资源浪费&#…

小米平板2装win10(附驱动)

前段时间在折腾着怎么给米pad2装win10&#xff0c;结果驱动什么的折腾了好久。 给米pad2装win10&#xff0c;其实就和给普通的电脑装win10差不多的步骤。 第一步&#xff0c;制作U盘启动器。工具什么的就用官方的winPE就好&#xff0c;iso就随意吧。 第二步&#xff0c;给米…

小米笔记本系统win10家庭版升级为企业版(专业版)

一.背景 新入职一家IT公司,由于公司领导层是小米粉,基本新入职的员工人手一本小米笔记本.小米笔记本默认自带的是家庭版的,由于之前公司很多人用的都是家庭版的,在某些极为特殊的软件开发情况下,家庭版的配置给开发带来了极大的困难,后来经过查资料验证企业版是不会出现这种情…

小米mix2s刷win11和android双系统

在给电脑安装系统的过程中&#xff0c;可能会因为各种原因出现windows无法安装的情况&#xff0c;我在给小米mix2s安装win11时发现出现了“计算机意外地重新启动或遇到错误&#xff0c;windows无法安装”的情况&#xff0c;下面就来教一下大家两种解决方法&#xff0c;希望可以…

小米air13.3一代的win10系统重装

仅作为记录&#xff0c;大佬请跳过 小米air的系统重装在进入bios之后&#xff0c;选择u盘启动时&#xff08;需要设置一个密码&#xff0c;然后关闭secure boot&#xff09;有点跟神船不一样&#xff0c;作为记录。 参考大佬博主文章传送门

Win10 IPv6 远程桌面连接(小米路由器)

前排广告&#xff1a;2021金三银四&#xff0c;字节跳动招人季&#xff0c;平均反馈时间仅1天&#xff01;选择覆盖达6大城市&#xff01;——2021年字节跳动飞书团队内推活动正式开启&#xff0c;岗位列表见&#xff1a;https://job.toutiao.com/s/eNtDcGu。除了这个投递连接外…

小米4A千兆刷OpenWrt_Win10

在Linux上试了一下&#xff0c;最终telnet 196.168.31.1失败&#xff0c;网上找了一些教程&#xff0c;改到win10下刷成功了。 1 先安装Pthon3 和pip3&#xff0c;然后pip3 install requests&#xff0c;不然会报错 2 win10开启telnet&#xff0c;方法简单自行百度&#xff1…

小米平板2可以装鸿蒙系统,详细教程!教你小米平板2轻松刷Win10

众所周知&#xff0c;小米平板2拥有MIUI和Windows 10两个版本&#xff0c;这两个版本在硬件上是一致的(除了机身存储空间不同)&#xff0c;所以理论上存在通刷的可能。 现在&#xff0c;有网友在MIUI论坛中共享了小米平板2刷Windows 10的教程&#xff0c;有兴趣的不妨一起来看看…

win10 下载

win10 下载 https://www.microsoft.com/zh-cn/software-download/windows10 Windows 10 2022 更新 l 版本 22H2 选择版本 以下 Windows 10 版本对于 Windows 10 家庭版和 Windows 10 专业版都有效。 如果您想验证下载数据的完整性和真实性&#xff0c;请按照以下步骤操作&…

计算机连接小米usb驱动,win10系统安装小米usb驱动的详细步骤

随着电脑的使用率越来越高&#xff0c;我们有时候可能会遇到对win10系统安装小米usb驱动进行设置&#xff0c;如果我们需要对win7系统安装小米usb驱动进行设置时&#xff0c;要怎么处理win10系统安装小米usb驱动的设置方法非常简单。 设置方法&#xff1a; 1、首先先下载小米驱…

win10 android 手机驱动下载,小米手机驱动win10驱动

小米手机usb驱动win10驱动是Win10系统专用的小米手机USB连接驱动&#xff0c;Win10电脑想要通过USB数据线与小米手机连接&#xff0c;必需安装这个驱动&#xff0c;从而可以使用电脑管理手机中的文件&#xff0c;以及进行线刷、解锁等操作&#xff0c;支持32位以及64位的Win10系…

【日常技巧】小米手机投屏至win10笔记本

最近需要多次实现自己手机与电脑的投屏&#xff0c;却又不想安装其他第三方软件&#xff0c;最终找到方法&#xff0c;做以下记录。 系统说明 手机&#xff1a;MIUI12.0.2稳定版 电脑&#xff1a;win10 前提条件 手机与电脑同处于同一wifi下 操作步骤 1.打开win10电脑投屏…

小米笔记本怎么恢复出厂的系统

买了台小米pro笔记本,中途自己重装了一次win10专业版,自己安装系统之后,自然很多电脑自带的软件和功能就没有了,比如Dolby,指纹解锁,正版的win10和office. 之前一直以为小米笔记本里面的软件都是预装在win10里面,只要有原厂的镜像就可以安装了,但是一直没找到.最近刚好系统又出…

小米笔记本pro15.6黑苹果+win10双系统/多系统

基本信息 配置,小米笔记本PRO 15.6 硬盘&#xff1a;杂牌 显卡&#xff1a;MX150/H610 CPU:i7-8550 简介&#xff1a;win10苹果双系统&#xff0c;双硬盘双系统&#xff0c;自带的pm981硬盘以前成功装过一次&#xff0c; 目前已知&#xff1a; MAC时间不同步&#xff08;…

小米pro安装win10系统

一.利用U盘做驱动盘 格式化u盘为NTFS格式官网下载https://www.microsoft.com/zh-cn/software-download/windows10点击立即下载工具 下载完成双击打开--->接受---->下一步---->为另一台电脑创建安装介质---->下一步--->下一步---->下一步---->出现所选U盘…

win10系统小米妙享中心,在手机可搜索到电脑,与之跨屏协作

在体验了小米妙享中心之后&#xff0c;发现非小米笔记本每次投屏不能直接在手机上直接投送到电脑屏幕&#xff0c;而只能在电脑打开手机画面&#xff0c;进行对手机操作&#xff0c;我们进行电脑伪装将我们的电脑变成小米笔记本&#xff0c;之后就可以在小米妙享中心发现我的设…

小米笔记本重装win10系统教程

U盘装机大师一键重装小米笔记本win10系统 小米笔记本自打推出以来&#xff0c;一直以非常高的性价比而深受大众的喜爱&#xff0c;加上其简约的外观&#xff0c;无论是价格还是外型都给了用户购买它的理由&#xff0c;对于电脑的话&#xff0c;重装系统是不可避免的事&#xf…

小米笔记本安装Win 10历程

今天要给小米笔记本&#xff08;128G 固态硬盘&#xff09;重新安装Win 10系统&#xff0c;本想着通过自带的恢复方式进行恢复 但是&#xff0c;通过此种方法进行还原后&#xff0c;电脑的 “设置” 点击不了了。无奈之下&#xff0c;只能通过U盘重新安装系统。 1. 通过U盘做系…