select函数详解

2023-11-17

select函数的功能和调用顺序

使用select函数可以完成非阻塞方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。
非阻塞方式:non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生,则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高。
select函数用来统一监视多个文件描述符的:
1、 是否存在套接字接收数据?
2、 无需阻塞传输数据的套接字有哪些?
3、 哪些套接字发生了异常?

select函数调用过程:
这里写图片描述
由上图知,调用select函数需要一些准备工作,调用后还需要查看结果。

设置文件描述符

select可以同时监视多个文件描述符(套接字)。
此时需要先将文件描述符集中到一起。集中时也要按照监视项(接收,传输,异常)进行区分,即按照上述3种监视项分成三类。
使用fd_set数组变量执行此项操作,该数组是存有0和1的位数组。
这里写图片描述
数组是从下标0开始,最左端的位表示文件描述符0。如果该位值为1,则表示该文件描述符是监视对象。
图上显然监视对象为fd1和fd3。

“是否应当通过文件描述符的数字直接将值注册到fd_set变量?”
当然不是!操作fd_set的值由如下宏来完成:

FD_ZERO(fd_set* fdset): 将fd_set变量的所有位初始化为0。
FD_SET(int fd, fd_set* fdset):在参数fd_set指向的变量中注册文件描述符fd的信息。
FD_CLR(int fd, fd_set* fdset):参数fd_set指向的变量中清除文件描述符fd的信息。
FD_ISSET(int fd, fd_set* fdset):若参数fd_set指向的变量中包含文件描述符fd的信息,则返回真。
这里写图片描述

设置监视范围及超时

select函数:

#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd, fd_set* readset, fd_set* writeset, fd_set* exceptset, 
const struct timeval* timeout);

select函数共有5个参数,其中参数和返回值:
maxfd:监视对象文件描述符数量。
readset:将所有关注“是否存在待读取数据”的文件描述符注册到fd_set变量,并传递其地址值。
writeset: 将所有关注“是否可传输无阻塞数据”的文件描述符注册到fd_set变量,并传递其地址值。
exceptset:将所有关注“是否发生异常”的文件描述符注册到fd_set变量,并传递其地址值。
timeout:调用select后,为防止陷入无限阻塞状态,传递超时信息。
返回值:错误返回-1,超时返回0。当关注的事件返回时,返回大于0的值,该值是发生事件的文件描述符数。

select函数用来验证3种监视项的变化情况。根据监视项声明3个fd_set变量,分别向其注册文件描述符信息,并把变量的地址传递到函数的第二到第四个参数。但是,在调用select函数前需要决定2件事:
“文件描述符的监视范围是?”
“如何设定select函数的超时时间?”

第一,文件描述符的监视范围与第一个参数有关。实际上,select函数要求通过第一个参数传递监视对象文件描述符的数量。因此,需要得到注册在fd_set变量中的文件描述符数。但每次新建文件描述符时,其值都会增1,故只需将最大的文件描述符值加1再传递到select函数即可。(加1是因为文件描述符的值从0开始)
第二,超时时间与最后一个参数有关。其中timeval结构体如下:

struct timeval
{
    long tv_sec;
    long tv_usec;
};

本来select函数只有在监视文件描述符发生变化时才返回,未发生变化会进入阻塞状态。指定超时时间就是为了防止这种情况发生。
将上述结构体填入时间值,然后将结构体地址值传给select函数的最后一个参数,此时,即使文件描述符中未发生变化,只要过了指定时间,也可以从函数返回。不过这种情况下,select函数返回0。 不想设置超时最后一个参数只需要传递NULL。

调用select函数后查看结果

如果select返回值大于0,说明文件描述符发生了变化。

关于文件描述符变化:
文件描述符变化是指监视的文件描述符中发生了相应的监视事件。
例如通过select的第二个参数传递的集合中存在需要读取数据的描述符时,就意味着文件描述符发生变化。

怎样获知哪些文件描述符发生了变化?向select函数的第二到第四个参数传递的fd_set变量中将产生变化,如下图:
这里写图片描述
select函数调用完成后,向其传递的fd_set变量中将发生变化。原来为1的所有位均变为0,但发生变化的文件描述符对应位除外。因此,可以认为值为1的位置上的文件描述符发生了变化。

select函数调用实例

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

#define BUF_SIZE 30

int main(int argc, char* argv[])
{
    fd_set reads,temps;
    int result, str_len;
    char buf[BUF_SIZE];
    struct timeval timeout;
    FD_ZERO(&reads);
    FD_SET(0, &reads);//监视文件描述符0的变化, 即标准输入的变化
    /*超时不能在此设置!
    因为调用select后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间.
    调用select函数前,每次都需要初始化timeval结构体变量.
    timeout.tv_sec = 5;
    timeout.tv_usec = 5000;*/
    while(1)
    {
        /*将准备好的fd_set变量reads的内容复制到temps变量,因为调用select函数后,除了发生变化的fd对应位外,
        剩下的所有位都将初始化为0,为了记住初始值,必须经过这种复制过程。*/
        temps = reads;
        //设置超时
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;

        //调用select函数. 若有控制台输入数据,则返回大于0的整数,如果没有输入数据而引发超时,返回0.
        result = select(1, &temps, 0, 0, &timeout);
        if(result == -1)
        {
            perror("select() error");
            break;
        }
        else if(result == 0)
        {
            puts("timeout");
        }
        else
        {
            //读取数据并输出
            if(FD_ISSET(0, &temps))
            {
                str_len = read(0, buf, BUF_SIZE);
                buf[str_len] = 0;
                printf("message from console: %s", buf);
            }
        }
    }

    return 0;
}

程序运行结果:

nihao
message from console: nihao
goodbye
message from console: goodbye
timeout
timeout

转载自:
https://blog.csdn.net/y396397735/article/details/55004775

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

select函数详解 的相关文章

  • chrom for ubuntu (Chrominum)的安装

    原文链接 http www ubuntugeek com how to install chromium google chrome in ubuntu using deb package html Chrominum的安装 1 编辑 et
  • centos7 RPM包之rpm命令

    RPM包与源码包的区别 1 软件包分类 源码包 C源代码包 rpm包 编译之后的二进制包 2 源码包 优点 开源 可以自由选择所需功能 可看源代码 卸载方便 直接删除安装位置 缺点 安装步骤过多 编译时间过长 3 RPM包 优点 使用简单
  • Linux命令-fsync

    对fsync命令只做简单介绍 不做详细原理解释 通过man命令查看fsync 2 函数有以下共识 1 fsync函数是属于系统核心函数 2 调用fsync函数会将修改的数据和文件描述符的属性持久化到存储设备中 3 fsync函数将内核缓存的
  • 计算机网络--linux下poll函数详解

    poll函数概述 select 和 poll 系统调用的本质一样 poll 的机制与 select 类似 与 select 在本质上没有多大差别 管理多个描述符也是进行轮询 根据描述符的状态进行处理 但是 poll 没有最大文件描述符数量的
  • Vi介绍及常用命令

    简要介绍 由加州大学伯克利分校 Bill Joy 研究开发 文本 编辑器有很多 比如图形模式的gedit kwrite OpenOffice 文本模式下的 编辑器有vi vim vi的增强版本 vi和vim是我们在Linux中最常用的 编辑
  • Linux 中的导出命令

    在本指南中 我们将了解 Linux 中的导出命令 Export 是 Bash shell 的内置命令 它用于标记要传递给子进程的变量和函数 基本上 变量将包含在子进程环境中 而不会影响其他环境 为了更清楚地了解我们正在讨论的内容 让我们深入
  • NGINX 作为 Node 或 Angular 应用程序的反向代理

    反向代理是一种从一个或多个上游服务器为客户端检索资源的服务器 它通常将自己置于专用网络中的防火墙后面 并将客户端请求转发到这些上游服务器 反向代理极大地提高了任何 Web 应用程序的安全性 性能和可靠性 许多用 NodeJS 或 Angul
  • 如何在 Ubuntu 18.04 上安装/卸载 NodeJS

    NodeJS 是一个 JavaScript 框架 可让您轻松构建快速的网络应用程序 在本指南中 我们将深入研究如何在 Ubuntu 18 04 上安装 NodeJS 步骤 1 将 NodeJS PPA 添加到 Ubuntu 18 04 首先
  • 在 Linux 中减小 PDF 文件大小

    在我们的 Linux 系统中 如果我们有一个很大的 PDF 文件 我们可能想减小它的大小 在本教程中 我们将了解在 Linux 中减小 PDF 大小或压缩 PDF 文件的不同方法 让我们找出一些命令行和 GUI 方法来处理这个问题 在 Li
  • 在 Ubuntu 18.04 上使用 Nginx 安装 WordPress

    WordPress是最受欢迎的开源内容管理系统 CMS 之一 与 Drupal 或 Joomla 等其他 CMS 相比 拥有高达 60 的市场份额 WordPress 可用于开发任何类型的网站 无论是博客 小型企业还是大型企业 凭借其免费和
  • Linux/UNIX 中的 ls 命令

    ls 命令是日常 Linux UNIX 操作中最常用的命令之一 该命令用于列出目录内的内容 是初学者从一开始就学习的少数命令之一 在本指南中 我们将讨论 Linux 中的常见 ls 命令以及可与该命令一起使用的其他参数 使用不带任何参数的
  • 用Vmware和vm tools虚拟机装Linux Ubuntu16 配置anaconda python3环境 安装tensorflow/tflearn

    Authoried by Monana Contact me via hemonan vip 163 com 本教程适合虚拟机 也适合不用虚拟机直接用Linux系统的 0 安装前的准备答疑 1 很多人都会有疑问 我到底在虚拟机里装linux
  • truss 命令

    truss 命令用途跟踪进程的系统调用 动态装入的用户级函数调用 接收的信号和造成的机器故障 语法truss f c a l d D e i t x Syscall s Signal m Fault r w FileDescriptor u
  • Linux/Unix 中的 AWK 命令

    AWK 适用于模式搜索和处理 该脚本运行以搜索一个或多个文件以识别匹配模式以及所述模式是否执行特定任务 在本指南中 我们将了解 AWK Linux 命令并了解它的功能 AWK 可以执行哪些操作 逐行扫描文件 将每个输入行拆分为字段 将输入行
  • Ubuntu18.04 windows10双系统安装解决grub引导问题

    最近给服务器的电脑升级了ubuntu18 直接用u盘安装 老是说grub引导问题 网上有很多教程真的坑人 说的含含糊糊的 不知道在卖弄什么关子 我参照这两个教程解决了安装问题 十分钟就装好了 感谢你们 https blog csdn net
  • select函数详解

    select函数的功能和调用顺序 使用select函数可以完成非阻塞方式工作的程序 它能够监视我们需要监视的文件描述符的变化情况 读写或是异常 非阻塞方式 non block 就是进程或线程执行此函数时不必非要等待事件的发生 一旦执行肯定返
  • 如何在 Linux/Ubuntu 中使用 PhotoRec 恢复已删除的文件

    不小心删除了文件或照片 在本教程中 我们将学习如何使用 PhotoRec 在 Linux 中恢复已删除的文件 在之前的教程中 我们讨论了使用名为的 Linux 实用程序恢复已删除文件的步骤TestDiskPhotoRec 实用程序是由同一家
  • C语言函数操作大全----(超详细)

    fopen 打开文件 相关函数 open fclose 表头文件 include
  • 在 Linux 中创建分区 - 分步指南

    在本教程中 我们将介绍在 Linux 中创建分区的步骤 这可以帮助您为特定用途分配不同的内存区域 创建分区还可以帮助您在计算机上安装多个操作系统 并最大限度地减少磁盘损坏时的损坏 如何在Linux中创建分区 在本教程中 我们将使用 fdis
  • 如何在 Linux 上安装 TestDisk 并恢复已删除的文件

    您是否曾经遇到过不小心删除文件的情况 在本教程中 我们将介绍如何在 Linux 中安装 TestDisk 并恢复已删除的文件 在本教程中 我将使用 Ubuntu 服务器进行工作 但即使您使用任何其他发行版 也可以遵循相同的步骤 唯一不同的是

随机推荐

  • el-checkbox如何同时获得value值和label的值

    在使用el checkbox时有时候需要往后台传送value值 定义的code 和label值 el checkbox组件默认获取的都是label属性中的值 如果label中设置的是code 那如何获取el checkbox的显示文字 la
  • 第一节 初识C语言

    第一节 初识C语言 目录 一 什么是C语言 二 第一个C语言程序 三 数据类型 四 变量与常量 五 字符串 转义字符 注释 六 结构 七 函数 八 数组 九 操作符 十 常见关键字 十一 define定义常量和宏 十二 指针 十三 结构体
  • 通过filebeat、logstash、rsyslog采集nginx日志的几种方式

    由于nginx功能强大 性能突出 越来越多的web应用采用nginx作为http和反向代理的web服务器 而nginx的访问日志不管是做用户行为分析还是安全分析都是非常重要的数据源之一 如何有效便捷的采集nginx的日志进行有效的分析成为大
  • postgresql教程

    postgreSQL教程目录 postgreSQL 创建数据库的方式 postgreSQL删除数据库的方式 PostgreSQL 创建表格 postgre删除表格 postgreSQL INSERT INTO 语句 postgreSQL S
  • Android中使用AES加密和解密

    Android中如何使用AES进行加密和解密 作为初入社会的IT行业的大专实习生 只能在公司里被当牛一样每天工作到半夜十二点以后 在这里也是第一次写博客 目的只有两个 1 记录技术实现 尽可能的帮助网友解决困难 2 吐槽公司 不多说了 直接
  • [每日设计] 01、小贱钟,基于STM32的手写机器人

    每日设计 01 小贱钟 基于STM32的手写机器人 原创 starger District 46实验室 3月25日 看厌了圆形的钟表 数字显示又太生硬 相信很多人和我一样 想换一个与众不同的方式看时间 小贱钟就是这样一个有趣的东东 它可以用
  • flask SQLAlchemy-ORM增删改查

    ORM介绍 随着项目越来越大 采用原生SQL的方式在代码中会出现大量的SQL语句 对项目的进展非常不利 SQL语句重复利用率不高 越复杂的SQL语句条件越多 代码越长 会出现很多相近似的SQL语句 很多SQL语句是在业务逻辑中拼出来的 如果
  • 文件ajax上传方式

    直接看代码 1 html table class layui table thead tr td width 20 产品信息 td td 产品信息 td tr thead tbody tr td 产品名称 td td td tr tbody
  • DOM之获取标签元素、属性和属性值

    1 获取标签元素 docunment getElementById id 只能获取一个id标签 docunment getElementByClassName class 获取class标签 结果是一个为数组 不能用forEach docu
  • 【自然语言处理】情感分析(一):基于 NLTK 的 Naive Bayes 实现

    情感分析 一 基于 NLTK 的 Naive Bayes 实现 朴素贝叶斯 Naive Bayes 分类器可以用来确定输入文本属于某一组类别的概率 例如 预测评论是正面的还是负面的 它是 朴素的 它假设文本中的单词是独立的 但在现实的自然人
  • Nginx中root和alias的区别

    root root指定的目录是上级目录 path匹配的整个路径会追加 即root path alias alias指定的目录必须带 path匹配后面的内容会在alias指定的目录下查找 即alias 匹配到path路径后面的部分 例 loc
  • C语言中的static 详细分析

    google了近三页的关于C语言中static的内容 发现可用的信息很少 要么长篇大论不知所云要么在关键之处几个字略过 对于想挖掘底层原理的初学者来说参考性不是很大 所以 我这篇博文博采众家之长 把互联网上的资料整合归类 并亲手编写程序验证
  • 仓鼠与厕鼠

    author skate time 2010 05 28 仓鼠与厕鼠 昨天晚上坐车回家的路上 看见来来往往的人流与车流 行走在高楼之间的马路上 心里当时有个触动 把自己抛离这个画面 站在一个全局的角度看 看似简单的画面 却让人感触很深 行走
  • [Windows驱动开发](一)序言

    笔者学习驱动编程是从两本书入门的 它们分别是 寒江独钓 内核安全编程 和 Windows驱动开发技术详解 两本书分别从不同的角度介绍了驱动程序的制作方法 在我理解 驱动程序可分为两类三种 第一类 传统型驱动 传统型驱动的特点就是所有的IRP
  • 解决网页不能复制或者答题不可粘贴

    F12 gt F1 gt Debugger Disable JavaScript 打勾
  • 用最简单的例子告诉你kafka是怎么用的

    1 首先打开zookeeper集群和kafka集群 三台都开上 2 创建 Kafka 主题 call 在任意几点创都可以 kafka topics sh zookeeper hadoop01 2181 topic call create r
  • Python每日练习题以及答案解析,还不进来测试一下?

    问题引入 现在有5个小朋友要分糖果 他们按照自己的编号顺序围坐在一张圆桌旁边 他们身上都有一些糖果 通过输入来决定每个小孩糖果的数量 从1号小朋友开始 将自己的糖果平均分成最多的3份 多出来的自己吃掉 自己留一份 其余两份分给他相邻的两位小
  • Python中字符串中函数rfind()用法

    Python中字符串中函数rfind 用法 1 rfind 函数概述 rfind 用来在一个字符串中查找一个字符串的最后出现时的索引位置 2 语法 str rfind substr beg 0 end len string rfind 方法
  • Jlink使用技巧之合并烧写文件

    文章目录 前言 准备 创建工程 1 打开JFlash 2 创建新工程 3 选择芯片的型号 4 打开要合并的程序文件1 bootloader hex 5 打开要合并的程序文件2 app hex 6 保存合并后的文件 注意 JLink软件的下载
  • select函数详解

    select函数的功能和调用顺序 使用select函数可以完成非阻塞方式工作的程序 它能够监视我们需要监视的文件描述符的变化情况 读写或是异常 非阻塞方式 non block 就是进程或线程执行此函数时不必非要等待事件的发生 一旦执行肯定返