Linux多路转接select,poll

news2024/11/27 3:50:12

文章目录

目录

文章目录

一、五种IO模型

1.阻塞IO:

2.非阻塞IO

3.信号驱动IO

4.IO多路转接

5.异步IO

二、高级IO的一些重要概念

1.同步通信和异步通信

2.阻塞和非阻塞

三、其他高级IO

四、非阻塞IO

1.fctl函数

2.实现setNoBlock函数,将文件描述符设置为非阻塞

3.轮询方式读取标准输入

五、IO多路转接之select

1.初始select

2.select函数原型

3.理解select执行过程

4.select的特点

5.select的缺点

6.select使用示例:检测标准输入输出

7.select使用实例

六、IO多路转接之poll

1.poll函数接口

2.参数说明

3.返回结果

4.poll的优点

5.poll的缺点

6.poll使用实例:使用poll监控标准输入

总结


一、五种IO模型

1.阻塞IO:

在内核将数据准备好之前,系统调用会一直等待。所有的套接字,默认都是阻塞方式。阻塞是最常见的IO模型。

2.非阻塞IO

如果内核还未将数据准备好,系统调用仍然会直接返回,并返回EWOULDBLOCK错误码。非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符,这个过程称为轮询。这对cpu来说是较大的浪费,一般只有特定的场景下才使用。

3.信号驱动IO

内核将数据准备好的时候,使用SIGIO信号通知应用程序进行IO操作

4.IO多路转接

虽然从图上看和阻塞IO类似,实际上最核心在于IO多路转接能够同时等待多个文件描述符的就绪状态。

5.异步IO

由内核在数据拷贝完成时,通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据)

在任何IO过程中,都包含两个步骤,第一是等待,第二是拷贝。而且在实际的应用场景中,等待消耗的时间往往都高于拷贝的时间,让IO高效,最核心的办法就是让等待的时间尽量减少。

二、高级IO的一些重要概念

1.同步通信和异步通信

同步和异步关注的是消息通信机制

  • 同步,就是在发出一个调用的时候,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到了返回值。换句话说,就是由调用者主动等待这个调用的结果
  • 异步则相反,调用在发出后,这个调用结果就直接返回,所以没有返回结果。换句话说,当一个异步调用发出后,调用者不会立刻得到返回结果;而是在调用发出后,被调用者通过状态、通知来通知调用者,或者通过回调函数处理这个调用

在多进程多线程的时候,也有提到同步和互斥。这里的是完全不同的概念。

进程/线程同步也是进程/线程之间直接的制约关系,是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系,尤其是在访问临界资源的时候。

2.阻塞和非阻塞

阻塞和非阻塞关注的是等待调用结果(消息,返回值)时的状态

  • 阻塞调用的指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回。
  • 非阻塞调用是指在不能立刻得到结果之前,该调用者不会阻塞当前线程。

三、其他高级IO

非阻塞io,纪录锁,系统V流机制,io多路转接(io多路复用),readv和writev函数以及存储映射IO(MMAP),这些统称为高级IO

本文重点讨论IO多路转接

四、非阻塞IO

1.fctl函数

fcntl 一个文件描述符,默认都是阻塞IO

#include<unistd.h>
#include<fcntl.h>

int fcntl(int fd,int cmd, .../*args */);

传入的cmd不同,后面追加的参数也不同

fcntl函数有5种功能:

  • 复制一个现有的描述符(cmd = F_DUPFD)
  • 获得/设置文件描述符标记(cmd = F_GETFD或F_SETFD)
  • 获得/设置文件状态标记(cmd = F_GETFL或F_SETFL)
  • 获得/设置异步io所有权(cmd = F_GETOWN或F_SETOWN)
  • 获得/设置记录锁(cmd = F_GETLK,F_SETLK或F_SETLKW)

此处使用第三个功能,获取/设置文件状态标记,就可以将一个文件描述符设置为非阻塞

2.实现setNoBlock函数,将文件描述符设置为非阻塞

基于fcntl实现一个SetNoBlock函数

void SetNoBlock(int fd)
{
    int fl = fcntl(fd,F_GETFL);
    if(fl <0)
    {
        perror("fcntl");
        return;
    }

    fcntl(fd,F_SETFL,fl|O_NONBLOCK);
}

使用F_GETFL将当前的文件描述符的属性取出来(这是一个位图).

然后再使用F_SETFL将文件描述符设置回去. 设置回去的同时, 加上一个O_NONBLOCK参数.

3.轮询方式读取标准输入

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>


void SetNoBlock(int fd)
{
    int fl = fcntl(fd,F_GETFL);
    if(fl <0)
    {
        perror("fcntl");
        return;
    }

    fcntl(fd,F_SETFL,fl|O_NONBLOCK);
}

int main()
{
    SetNoBlock(0);
    while(1)
    {
        char buf[1024] = {0};
        ssize_t read_size = read(0,buf,sizeof(buf)-1);
        if(read_size <0)
       {
         sleep(1);
         continue;
       }

       printf("input:%s\n",buf);
       return 0;
}

五、IO多路转接之select

1.初始select

系统提供select函数来实现多路复用输入/输出模型

  • select系统调用是用来让我们的程序监视多个fd的状态变化的
  • 程序会停在select这里等待,直到被监视的fd有一个或者多个发生了状态改变

2.select函数原型

#include<sys/select.h>

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

//nfd 是需要监视的最大文件描述符值+1
//rdset,wrset,exset分别对应需要检测的可读文件描述符的集合,可写文件描述符的集合,以及异常文件描述符的集合
//timeout为结构timeval,用来设置select的等待时间

参数timeout取值:

  • NULL:则表示select()没有timeout,select将一直被阻塞,直到某个文件描述符上发生了事件
  • 0:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生
  • 特定的结构值:如果在指定的时间段内没有事件发生,select将超时返回。

fd_set结构

这个结构就是一个整数数组,更严格的说,是一个位图,使用位图中对应的位来表示要监视的文件描述符,有一组fd_set接口,来比较方便操作位图

void FD_CLR(int fd, fd_set *set); // 用来清除描述词组set中相关fd 的位
int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组set中相关fd 的位是否为真
void FD_SET(int fd, fd_set *set); // 用来设置描述词组set中相关fd的位
void FD_ZERO(fd_set *set); // 用来清除描述词组set的全部位

关于timeval结构

timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0

strcut timeval
{
    __time_t tv_sec;   //seconds
    __suseconds_t tv_usec;   //microseconds
};

函数返回值:

  • 执行成功则返回文件描述词状态已改变的个数
  • 如果返回0代表在描述词状态改变前已经超过timeout时间,没有返回
  • 当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds,exceptfds和timeout的值变成不可预测

错误值可能为:

  • EBADF 文件描述词为无效的或者该文件已关闭
  • EINTR 此调用被信号中断
  • EINVAL 参数n为负值
  • ENOMEN 核心内存不足

常见使用场景:

fs_set readset;
FD_SET(fd,&readset);
select(fd+1,&readset,NULL,NULL,NULL);
if(FD_ISSET(fd,readset)){...}

3.理解select执行过程

理解select模型的关键在于理解ds_set,这里取fd_set长度为1字节,fd_set中的每一个bit可以对应一个文件描述符fd,则1字节长的fd_set最大可以对应8个fd

  1. 执行fd_set set; FD_ZERO(&set); 则set用位表示是0000 0000
  2. 若fd = 5 执行FD_SET(fd,&set);后变为0001 0000
  3. 若再加入fd = 2,fd = 1,则set变成 0001 0011
  4. 执行select(6,&set,0,0,0); 阻塞等待
  5. 若fd = 1,fd = 2 上都发生可读事件,则select返回,此时set变为0000 0011
  6. 注意,没有事件发生的fd = 5被清空

4.select的特点

  • 可监控的文件描述符个数取决与sizeof(fd_set)的值,比如sizeof(fd_set)=512,每bit表示一个文件描述符,则服务器上支持的最大文件描述符是512*8 = 4096
  • 将fd加入select监控集的同时,还要再使用一个数据结构array进行FD_ISSET判断
  • select返回后会把以前加入但是没有发生事件的fd清空,则每次开始select前都要重新从array取得fd逐一加入,扫描array的同时取得fd的最大maxfd,用于select的第一个参数

5.select的缺点

  • 每次调用select,都需要手动设置fd集合,从接口使用角度也非常不便
  • 每次调用select,都需要把fd从用户态拷贝到内核态,这个开销在fd很多时会很大
  • 同时每次调用select都需要在内核遍历传入的所有fd,fd很多的时候开销很大
  • select支持的文件描述符数量太少

6.select使用示例:检测标准输入输出

#include<stdio.h>
#include<unistd.h>
#include<sys/select.h>

int main()
{
    fd_set read_fds;
    FD_ZERO(&read_fds);
    FD_SET(0,&read_fds);
    for(;;)
    {
        printf("> ");
        fflush(stdout);
        int ret = select(1,&read_fds,NULL,NULL,NULL);
        if(ret <0)
        {
            perror("select");
            continue;
        }

        if(FD_ISSET(0,&read_fds))
        {
            char buf[1024] = {0};
            read(0,buf,sizeof(buf)-1);
            printf("input:%s",buf);
        }

        else
        {
            printf("invalid fd");
            continue;
         }
        FD_ZERO(&read_fds);
        FD_SET(0,&read_fds);
    }
    return 0;
}

7.select使用实例

参照gitee,实现select字典服务器

六、IO多路转接之poll

1.poll函数接口

#include<poll.h>

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

//pollfd结构
struct pollfd{
    int fd;
    short events;  //requested events
    short revents; // returned events
};

2.参数说明

  • fds是一个poll函数监听的结构列表,每一个元素中包含3部分内容:fd,监听的事件集合,返回的事件集合
  • nfds表示fds数组的长度
  • timeout表示poll函数的超时时间,单位是ms

3.返回结果

返回值小于0,表示出错

返回值等于0,表示poll函数等待超时

返回值大于0,表示poll由于监听的fd就绪而返回

4.poll的优点

不同与select使用三个位图来表示fdset的方式,poll使用一个pollfd指针实现

  • pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式,接口使用比select更方便
  • poll没有max数量限制(但是数量过大后性能也是会下降)

5.poll的缺点

poll中监听的文件fd增多时

  • 和select函数一样,poll返回后,需要轮询pollfd来获取就绪的fd
  • 每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中
  • 同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的fd数量增加,效率也会线性下降

6.poll使用实例:使用poll监控标准输入

#include <poll.h>
#include <unistd.h>
#include <stdio.h>
int main() {
 struct pollfd poll_fd;
 poll_fd.fd = 0;
 poll_fd.events = POLLIN;

 for (;;) {
 int ret = poll(&poll_fd, 1, 1000);
 if (ret < 0) {
 perror("poll");
 continue;
 }
 if (ret == 0) {
 printf("poll timeout\n");
 continue;
 }
 if (poll_fd.revents == POLLIN) {
 char buf[1024] = {0};
 read(0, buf, sizeof(buf) - 1);
 printf("stdin:%s", buf);
 }
 }
}

总结

本文主要介绍了select和poll,下一篇文章详解epoll

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1259756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OSG编程指南<三>:利用Cmake+VS2019+OSG3.6.5编译osgVerse

目前osgearth的ralease版本和debugx64都已经编译过了并且自测可用&#xff0c;放到资源里osgearth下载&#xff0c;供需要的朋友下载参考。环境配置&#xff1a;win10VS2017OSG3.6.4OSGEarth2.10.2&#xff0c; 1、配置OSG环境 编译好osg&#xff0c;然后在系统变量中配置如下…

微服务--02--Nacos注册中心

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 服务注册和发现手动发送Http请求的方式存在问题注册中心原理 Nacos注册中心配置服务注册服务发现小结&#xff1a; 服务注册和发现 手动发送Http请求的方式存在问题…

windows中打开psql命令行

第一种方式 1.点击下方的psql&#xff0c;打开命令行窗口 2.中括号中的是默认值&#xff0c;直接回车就行 3.成功 第二种方式 双击安装目录中的执行文件 “D:\soft\postgresql\catalogue\scripts\runpsql.bat” 第三种方式 1.加到环境变量 把“D:\soft\postgresql\catalo…

Python爬虫入门课: 如何实现数据抓取 <文字 图片 音频 视频 文档..>

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 环境使用: Python 3.10 解释器 Pycharm 编辑器 模块使用: requests re csv pandas 爬虫实现第一步: 一. 抓包分析 找到对应数据链接地址 套用代码: 修改…

创建JDK8版本的SpringBoot项目的方法

截止到2023.11.24&#xff0c;SpringBoot不再支持3.0X之前的版本&#xff0c;3.0X之后的版本所对应的JDK版本为JDK17&#xff0c;下面介绍如何在idea上继续使用JDK8的版本。 一.通过阿里云下载 https://start.aliyun.com/https://start.aliyun.com/ 点击高级选项进行详细设置…

centos 显卡驱动安装(chatglm2大模型安装步骤一)

1.服务器配置 服务器系统:Centos7.9 x64 显卡:RTX3090 (24G) 2.安装环境 2.1 检查显卡驱动是否安装 输入命令:nvidia-smi(显示显卡信息) 如果有以下显示说明,已经有显卡驱动。否则需要重装。 2.2 下载显卡驱动 第一步:浏览器输入https://www.nvidia.cn/Downloa…

20231127让RK3399的挖掘机开发板在Andorid12系统下休眠唤醒之后禁止锁屏

20231127让RK3399的挖掘机开发板在Andorid12系统下休眠唤醒之后禁止锁屏 2023/11/27 20:55 适用于SOC以及系统版本&#xff1a; RK3399&#xff1a;Android10/11/12 RK3568&#xff1a;Android11/12 RK3588&#xff1a;Android12 当RK3399平台的Android12系统在休眠之后&#x…

SpringBoot定时任务报错Unexpected error occurred in scheduled task原因及其解决方法(亲测有效)

问题 spring boot项目在线上一直正常运行没有错误&#xff0c;然后今天发生了报错&#xff0c;如图 这是一个定时器错误&#xff0c;发生这个报错 主要有两个原因 定时器编写的有错误Scheduled注解方式级别高于资源注入级别&#xff0c;导致了资源注入失败 以下是我的代码 …

企业如何保障跨境金融业务中的数据安全传输?

随着全球化的不断深入&#xff0c;跨境金融业务日益频繁&#xff0c;然而在这些业务中&#xff0c;数据的安全传输一直是企业面临的重大挑战。跨境业务数据传输可能会遇到多种困难&#xff0c;如网络攻击、数据泄露、通信故障等。因此&#xff0c;企业需要采取有效的措施来确保…

centos7 keepalived 探测哪个是当前节点

前提 nginx 默认页面内容中需要加上各节点的ip nginx web页面修改 nginx配置文件路径&#xff1a;/etc/nginx/nginx.conf&#xff0c;该配置文件引用了/etc/nginx/conf.d/default.conf 打开/etc/nginx/conf.d/default.conf配置文件可以看到html页面的路径 /usr/share/nginx…

判断二进制最低位数字

在二进制表示中&#xff0c;偶数的最低位&#xff08;最右边一位&#xff09;始终为0&#xff0c;而奇数的最低位始终为1。 当一个数与1进行按位与运算时&#xff0c;实际上是在检查该数的最低位是0还是1。 如果结果为0&#xff0c;则说明这个数是偶数&#xff0c;因为偶数的…

中文编程开发工具高级版全部构件工具箱列表,中文编程自由版下载

中文编程开发工具高级版全部构件工具箱列表&#xff0c;中文编程自由版下载 附&#xff1a;中文编程工具构件工具箱总共22组305个构件&#xff0c;构件明细如下&#xff1a;文本件16个&#xff1a; &#xff08;普通标签&#xff0c;连接标签&#xff0c;闪动标签&#xff0c;立…

nodejs+vue+elementui网上家电家用电器数码商城购物网站 多商家

基于vue.js的恒捷网上家电商城系统根据实际情况分为前后台两部分&#xff0c;前台部分主要是让用户购物使用的&#xff0c;包括用户的注册登录&#xff0c;查看公告&#xff0c;查看和搜索商品信息&#xff0c;根据分类定位不同类型的商品&#xff0c;将喜欢的商品加入购物车&a…

搭建Appium工具环境

1、安装Java Development Kit&#xff08;JDK&#xff09; 前往Oracle官网下载JDK。 在https://www.oracle.com/java/technologies/javase-jdk11-downloads.html 找到最新版本的JDK。根据操作系统选择适合的版本&#xff0c;并根据指示下载安装程序。 安装JDK。运行下载的安…

Django整合回顾

web应用 什么是web&#xff1a;通过web访问web应用程序&#xff0c;很方便&#xff0c;用户只需要一个浏览器即可。是典型的浏览器/服务器端架构的产物 cs架构与bs架构 应用程序有C/S B/S两种模式&#xff1a;b/s 本质上还是c/s mysql属于c/s架构&#xff0c;只是我们的服务…

《金融科技行业2023年专利分析白皮书》发布——科技变革金融,专利助力行业发展

金融是国民经济的血脉&#xff0c;是国家核心竞争力的重要组成部分&#xff0c;金融高质量发展成为2023年中央金融工作的重要议题。《中国金融科技调查报告》中指出&#xff0c;我国金融服务业在科技的助力下&#xff0c;从1.0时代的“信息科技金融”、2.0时代的“互联网金融”…

【电路笔记】-电阻器颜色代码与阻值计算

电阻器颜色代码与阻值计算 文章目录 电阻器颜色代码与阻值计算1、概述2、计算电阻器颜色代码值3、贴片电阻器 电阻器颜色编码使用色带轻松识别电阻器的电阻值及其百分比容差。 1、概述 由于有许多不同类型的电阻器可用&#xff0c;我们需要形成电阻器颜色代码系统以便能够识别…

常见面试题-Netty中ByteBuf类

了解 Netty 中的 ByteBuf 类吗&#xff1f; 答&#xff1a; 在 Java NIO 编程中&#xff0c;Java 提供了 ByteBuffer 作为字节缓冲区类型&#xff08;缓冲区可以理解为一段内存区域&#xff09;&#xff0c;来表示一个连续的字节序列。 Netty 中并没有使用 Java 的 ByteBuff…

计算机毕业设计|基于SpringBoot+MyBatis框架的仿天猫商城购物系统设计与实现

计算机毕业设计|基于SpringBootMyBatis框架的仿天猫商城购物系统设计与实现 迷你仿天猫商城是一个基于SSM框架的综合性B2C电商平台&#xff0c;需求设计主要参考天猫商城的购物流程&#xff1a;用户从注册开始&#xff0c;到完成登录&#xff0c;浏览商品&#xff0c;加入购物…

操作系统的中断与异常(408常考点)

为了进行核心态和用户态两种状态的切换&#xff0c;引入了中断机制。 中断是计算机系统中的一种事件&#xff0c;它会打断CPU当前正在执行的程序&#xff0c;转而执行另一个程序或者执行特定的处理程序。中断可以来自外部设备&#xff08;如键盘、鼠标、网络等&#xff09;、软…