当前位置: 首页 > news >正文

网络编程之多路复用---mutilio

IO多路复用技术

目录

  1. 定义
  2. 作用
  3. 并发与并行
  4. IO模型
  5. 阻塞IO
  6. 非阻塞IO
  7. 信号驱动IO
  8. 并行模型
  9. IO多路复用
  10. select函数详解
  11. select/poll/epoll区别
  12. 作业要求

1. 定义

单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力

2. 作用

应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标的输入、中断信号等等事件,再比如web服务器如nginx,需要同时处理来来自N个客户端的事件。

3. 并发与并行

逻辑控制流在时间上的重叠叫做 并发
并行

而CPU单核在同一时刻只能做一件事情,一种解决办法是对CPU进行时分复用(多个事件流将CPU切割成多个时间片,不同事件流的时间片交替进行)。在计算机系统中,我们用线程或者进程来表示一条执行流,通过不同的线程或进程在操作系统内部的调度,来做到对CPU处理的时分复用。这样多个事件流就可以并发进行,不需要一个等待另一个太久,在用户看起来他们似乎就是并行在做一样。

使用并发处理的成本:

  • 线程/进程创建成本
  • CPU切换不同线程/进程成本 Context Switch 上下文切换 页表,寄存器,缓存
  • 多线程的资源竞争

有没有一种可以在单线程/进程中处理多个事件流的方法呢?一种答案就是IO多路复用。

因此IO多路复用解决的本质问题是在用更少的资源完成更多的事。

4. IO模型

  1. 阻塞IO
  2. 非阻塞IO EAGAIN 忙等待 errno
  3. 信号驱动IO SIGIO 用的相对少(了解)
  4. 并行模型 进程,线程
  5. IO多路复用 select、poll、epoll

1.阻塞IO ===》最常用 默认设置

2.非阻塞IO ===》在阻塞IO的基础上调整其为不再阻塞等待。

在程序执行阶段调整文件的执行方式为非阻塞:
===》fcntl() ===>动态调整文件的阻塞属性

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

功能:修改指定文件的属性信息。
参数:fd 要调整的文件描述符
cmd 要调整的文件属性宏名称
… 可变长的属性值参数。
返回值:成功 不一定,看cmd
失败 -1;

eg:修改文件的非阻塞属性:

int flag ;
flag  = fcntl(fd,F_GETFL,0);  ///获取fd文件的默认属性到flag变量中。
flag  = flag | O_NONBLOCK;    ///将变量的值调整并添加非阻塞属性
fcntl(fd,F_SETFL,flag);       ///将新属性flag设置到fd对应的文件生效。

以上代码执行后的阻塞IO将变成非阻塞方式。

3.信号驱动io

文件描述符需要追加 O_ASYNC 标志。
设备有io事件可以执行时,内核发送SIGIO信号。

1.追加标志

int flag ;
flag  = fcntl(fd,F_GETFL,0);
fcntl(fd,F_SETFL,flag | O_ASYNC);    

2.设置信号接收者

fcntl(fd,F_SETOWN,getpid());//常用设置

3.对信号进行捕获

signal(SIGIO,myhandle);//

4.并行

1.进程
2.线程

5. IO多路复用 ===》并发服务器 ===》TCP协议

3.select循环服务器 ===> 用select函数来动态检测有数据流动的文件描述符

#include <sys/select.h>
#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);

功能:完成指定描述符集合中有效描述符的动态检测。
该函数具有阻塞等待功能,在函数执行完毕后
目标测试集合中将只保留最后有数据的描述符。

参数:nfds 描述符的上限值,一般是链接后描述符的最大值+1;
readfds 只读描述符集
writefds 只写描述符集
exceptfds 异常描述符集
以上三个参数都是 fd_set * 的描述符集合类型
timeout 检测超时 如果是NULL表示一直检测不超时 。

返回值:超时 0
失败 -1
成功 >0

为了配合select函数执行,有如下宏函数:

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 poll epoll的区别

  1. select
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
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的调用一般要注意几点:
① readfds等是指针结果参数,会被函数修改…
② 要注意计算nfds…
③ timeout如果为NULL表示阻塞等…
④ select返回-1表示错误…
⑤ Linux的实现中select返回时会将timeout修改为剩余时间…

select的缺点在于:
① 由于描述符集合set的限制…
② 返回的可读集合是个fdset类型…
③ nfds的存在就是为了解决select的效率问题…

  1. epoll
int epoll_create(int size)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);

epoll 解决了select和poll的几个性能上的缺陷…
epoll显著提高性能的前提是…
epoll的另外区别是…

作业

使用以上任意一个并发服务器模型,完成如下功能:

  1. 可以向服务器发送一个消息,并在服务器端打印输出该消息的来源ip+port
  2. 将所有的连接终端的个数统计出来

本小节知识总结:io多路复用

IO模型
1.阻塞io 闲等待 让出CPU
2.非阻塞 IO EAGAIN 忙等待errno,不会让出CPU 反复检测io的状态 ,使用fcntl O_NONBLG
3.并行io,进程或者线程,相对多路io而言,比较消耗系统资源
4.多路io,可以处理,单线程或者单进程中,多个阻塞io,select epoll;

多路io复用:由操作系统对io事件进行检测的机制

select:
1.创建集合
2.加入关心的文件描述符;
3.调用select 等待io事件(读或写,大部分情况是读)的到来
4.找出对应的fd’,进行读或者写的操作。
5.清除标志位(读写标志位)
epoll
1.创建集合(epoll_wait)
2.加入关心的文件描述符epoll-ctl
3.调用epoll_wait等待io事件(读或者写,大部分情况是读)的到来,并把就绪fd存入就绪集合(rev示例中的rev)
4.在rev集合中找出对应的fd,进行读写操作
对照优缺点
select:最多检测1024个fd;epoll 一般对于服务器而言<5000 fd
select:在检测文件fd式是轮询的方式,一个个文件包描述符询问检测;epoll检测方式:主动上报,通知了才会去:设备通知epoll,epoll通知a.out;
select:在找对应的fd时,需要在原始集合里面(就绪和未就绪在一起)找;epoll:rev集合里(只有就绪的fd)中找出对应的fd;

http://www.dtcms.com/a/296699.html

相关文章:

  • tauri实用教程:阻止除控制台关闭程序外的全部手动关闭
  • 大模型-batch之static batch
  • 基于Matlab图像处理的水果分级系统
  • 【软件与环境】--Visual Studio2022安装教程
  • JMeter压测黑马点评优惠券秒杀的配置及请求爆红问题的解决(详细图解)
  • 在Ubuntu上使用QEMU学习RISC-V程序(2)gdb调试
  • 2025年7月23日 AI 今日头条
  • C++ 基础入门
  • 144. 二叉树的前序遍历
  • rt-thread加一个库
  • matrix-breakout-2-morpheus靶机通关教程
  • Android Studio历史版本快速下载(二次修改记录)
  • Shell的正则表达式
  • (nice!!!)(LeetCode 每日一题) 2322. 从树中删除边的最小分数 (深度优先搜索dfs + 树)
  • linux C -glib库的基本使用
  • 【华为机试】1208. 尽可能使字符串相等
  • 蚁群优化算法(Ant Colony Optimization, ACO)简介
  • Scrcpy启动闪退
  • Function Calling:让大模型学会使用工具
  • es0102---语法格式、数据类型、整合springboot、创建库、创建映射、新增数据、自定义查询
  • tensorflow搭建神经网络
  • SQL基础⑩ | 数据类型篇
  • 哈希表模拟实现
  • Java学习日记_廖万忠
  • Spring Cloud Alibaba Sentinel 源码阅读之流量控制算法
  • C++编程基础四大件
  • Bright Data 实战指南:从竞品数据抓取到电商策略优化全流程
  • 探秘 VSAR软件:CAN报文转DBC信号的便捷工具
  • 力扣189:轮转数组
  • 5 个适合创意创作的网站,灵感不设限