Select()系统调用及文件描述符集fd_set的应用

混合整数规划(MIP)在资源优化中的实战应用 本文深入探讨了混合整数规划(MIP)在资源优化中的实战应用,从菜市场采购到工厂调度,再到物流配送和钢铁厂切割问题。通过分支定界法和割平面法等技术,MIP能够有效解决包含整数和连续变量的复杂优化问题,提升企业运营效率。文章还介绍了现代求解器的优化策略和实际项目中的避坑指南,帮助读者更好地应用MIP技术。 阅读详情

Select()系统调用及文件描述符集fd_set的应用
湖南省衡阳市环境工程公司网络中心 张 卿

在网络程序中,一个进程同时处理多个文件描述符是很常见的情况。select()系统调用可以使进程检测同时等待的多个I/O设备,当没有设备准备好时,select()阻塞,其中任一设备准备好时,select()就返回。
select()的调用形式为:
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd, fd_set *readfds, fd_set *writefds, fe_set *exceptfds, const struct timeval *timeout);
select的第一个参数是文件描述符集中要被检测的比特数,这个值必须至少比待检测的最大文件描述符大1;参数readfds指定了被读监控的文件描述符集;参数writefds指定了被写监控的文件描述符集;而参数exceptfds指定了被例外条件监控的文件描述符集。
参数timeout起了定时器的作用:到了指定的时间,无论是否有设备准备好,都返回调用。timeval的结构定义如下:
struct timeval{
long tv_sec; //表示几秒
long tv_usec; //表示几微妙
}
timeout取不同的值,该调用就表现不同的性质:
1.timeout为0,调用立即返回;
2.timeout为NULL,select()调用就阻塞,直到知道有文件描述符就绪;
3.timeout为正整数,就是一般的定时器。
select调用返回时,除了那些已经就绪的描述符外,select将清除readfds、writefds和exceptfds中的所有没有就绪的描述符。select的返回值有如下情况:
1.正常情况下返回就绪的文件描述符个数;
2.经过了timeout时长后仍无设备准备好,返回值为0;
3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。
4.如果出错,返回-1并设置相应的errno。
系统提供了4个宏对描述符集进行操作:
#include <sys/select.h>
#include <sys/time.h>
void FD_SET(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
void FD_ISSET(int fd, fd_set *fdset);
void FD_ZERO(fd_set *fdset);
宏FD_SET设置文件描述符集fdset中对应于文件描述符fd的位(设置为1),宏FD_CLR清除文件描述符集fdset中对应于文件描述符fd的位(设置为0),宏FD_ZERO清除文件描述符集fdset中的所有位(既把所有位都设置为0)。使用这3个宏在调用select前设置描述符屏蔽位,在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。
过去,描述符集被作为一个整数位屏蔽码得到实现,但是这种实现对于多于32个的文件描述符将无法工作。描述符集现在通常用整数数组中的位域表示,数组元素的每一位对应一个文件描述符。例如,一个整数占32位,那么整数数组的第一个元素代表文件描述符0到31,数组的第二个元素代表文件描述符32到63,以此类推。宏FD_SET设置整数数组中对应于fd文件描述符的位为1,宏FD_CLR设置整数数组中对应于fd文件描述符的位为0,宏FD_ZERO设置整数数组中的所有位都为0。假设执行如下程序后:
#include <sys/select.h>
#include <sys/time.h>
fd_set readset;
FD_ZERO(&readset);
FD_SET(5, &readset);
FD_SET(33, &readset);
则文件描述符集readset中对应于文件描述符6和33的相应位被置为1,如图1所示:

再执行如下程序后:
FD_CLR(5, &readset);
则文件描述符集readset对应于文件描述符6的相应位被置为0,如图2所示:

通常,操作系统通过宏FD_SETSIZE来声明在一个进程中select所能操作的文件描述符的最大数目。例如:
在4.4BSD的头文件中我们可以看到:
#ifndef FD_SETSIZE
#define FD_SETSIZE 1024
#endif
在红帽Linux的头文件<bits/types.h>中我们可以看到:
#define __FD_SETSIZE 1024
以及在头文件<sys/select.h>中我们可以看到:
#include <bits/types.h>
#define FD_SETSIZE __FD_SETSIZE
既定义FD_SETSIZE为1024,一个整数占4个字节,既32位,那么就是用包含32个元素的整数数组来表示文件描述符集。我们可以在头文件中修改这个值来改变select使用的文件描述符集的大小,但是必须重新编译内核才能使修改后的值有效。当前版本的unix操作系统没有限制FD_SETSIZE的最大值,通常只受内存以及系统管理上的限制。
我们明白了文件描述符集的实现机制之后,就可对其进行灵活运用。(以下程序在红帽Linux 6.0下运行通过,函数fd_isempty用于判断文件描述符集是否为空;函数fd_fetch取出文件描述符集中的所有文件描述符)
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
struct my_fd_set{
fd_set fs; //定义文件描述符集fs
unsigned int nconnect; //文件描述符集fs中文件描述符的个数
unsigned int nmaxfd; //文件描述符集fs中最大的文件描述符
};
/* 函数fd_isempty用于判断文件描述符集是否为空,为空返回1,不为空则返回0 */
int fd_isempty(struct my_fd_set *pfs)
{
int i;
/* 文件描述符集fd_set是通过整数数组来实现的,所以定义整数数组myset的元素个数为文件描述符集fd_set所占内存空间的字节数除以整数所占内存空间的字节数。
*/
unsigned int myset[sizeof(fd_set) / sizeof(int)];
/* 把文件描述符集pfs->fs 拷贝到数组myset */
memcpy(myset, &pfs->fs, sizeof(fd_set));
for(i = 0; i < sizeof(fd_set) / sizeof(int); i++)
/* 如果myset的某个元素不为0,说明文件描述符集不为空,则函数返回0 */
if (myset[i])
return 0;
return 1; /* 如果myset的所有元素都为0,说明文件描述符集为空,则函数返回1 */
}
/* 函数fd_fetch对文件描述符集进行位操作,把为1的位换算成相应的文件描述符,然后就可对其进行I/O操作 */
void fd_fetch(struct my_fd_set *pfs)
{
struct my_fd_set *tempset; //定义一个临时的结构指针
unsigned int myset[sizeof(fd_set)/sizeof(unsigned int)];
unsigned int i, nbit, nfind, ntemp;
tempset = pfs;
memcpy(myset, &tempset->fs, sizeof(fd_set));
/* 把最大的文件描述符maxfd除以整数所占的位数,得出maxfd在文件描述符集中相应的位对应于整数数组myset的相应元素的下标,目的是为了减少检索的次数 */
nfind = tempset->nmaxfd / (sizeof(int)*8);
for (i = 0; i <= nfind; i++) {
/* 如果数组myset的某个元素为0,说明这个元素所对应的文件描述符集的32位全为0,则继续判断下一元素。*/
if (myset[i] == 0) continue;
/* 如果数组myset的某个元素不为0,说明这个元素所对应的文件描述符集的32位中有为1的,把myset[i]赋值给临时变量ntemp,对ntemp进行位运算,把为1的位换算成相应的文件描述符 */
ntemp = myset[i];
/* nbit记录整数的二进制位数,对ntemp从低到高位进行&1运算,直到整数的最高位,或直到文件描述符集中文件描述符的个数等于0 */
for (nbit = 0; tempset->nconnect && (nbit < sizeof(int)*8); nbit++) {
if (ntemp & 1) {
/* 如果某位为1,则可得到对应的文件描述符为nbit + 32*I,然后我们可对其进行I/O操作。这里我只是做了简单的显示。*/
printf("i = %d, nbit = %d, The file description is %d/n", i, nbit, nbit + 32*i);
/* 取出一个文件描述符后,将文件描述符集中文件描述符的个数减1 */
tempset->nconnect--; }
ntemp >>= 1; // ntemp右移一位
}
}
}

/* 下面的主程序是对以上两个函数的测试 */
main()
{
/* 假设fd1,fd2,fd3为3个文件描述符,实际运用中可为Socket描述符等 */
int fd1 = 7, fd2 = 256, fd3 = 1023, isempty;
struct my_fd_set connect_set;
connect_set.nconnect = 0;
connect_set.nmaxfd = 0;
FD_ZERO(&connect_set.fs);
/* FD_SET操作前对函数fd_isempty进行测试 */
isempty = fd_isempty(&connect_set);
printf("isempty = %d/n", isempty);
FD_SET(fd1, &connect_set.fs);
FD_SET(fd2, &connect_set.fs);
FD_SET(fd3, &connect_set.fs);
connect_set.nconnect = 3;
connect_set.nmaxfd = fd3 ;
/* FD_SET操作后,既把文件描述符加入到文件描述符集之后,对函数fd_isempty进行测试 */
isempty = fd_isempty(&connect_set);
printf("isempty = %d/n", isempty);
/* 对函数fd_ fetch进行测试 */
fd_fetch(&connect_set);
}

/* 程序输出结果为 :*/
isempty is 1
isempty is 0
i = 0, nbit = 7, The file description is 7
i = 8, nbit = 0, The file description is 256
i = 31, nbit = 31, The file description is 1023

LVGL在单色屏上运行 本文主要讲述LVGL在单色屏应用中的实现思路,并已验证通过。网上关于lvgl移植的文章有很多了,本文不加以赘述。 阅读详情

相关推荐

基于CANoe的车载以太网测试

以太网测试 CANoe

Yafet 4554

使用 `select` 实现文件描述符监控的深入解析与示例

在编程中,`select` 函数可以用于监控多个文件描述符(包括 socket、串口和普通文件),以等待它们变为可读、可写或发生错误事件。本文将重点介绍 `select` 在监控普通文件描述符(句柄)时的行为,并提供实际的 C++ 代码示例。

Where there is life, there is hope. 1076

【G4基础08】GPS-2-Macro Commands宏命令

GPS-2

adelall的博客 3738

select函数详解

select函数的功能和调用顺序 使用select函数可以完成非阻塞方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。 非阻塞方式:non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生,则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高...

hmxz2nn的博客 4万+

彻底解决0x80070005错误代码:全面分析与实战指南

0x80070005错误代码虽然令人头疼,但通过上述方法,我们完全有能力将其攻克。从检查磁盘空间、设置账号权限,到运行疑难解答和系统文件检查器,再到调整相关服务状态,每一步都是解决这一问题的关键。希望本文能为你提供有力的帮助,让你在使用Windows系统的过程中更加顺畅无忧。

nntxthml的博客 6935

告别‘抓瞎’:CANoe的Trace、Graphics和Logging窗口实战技巧,高效分析总线故障

本文深入解析CANoe的Trace、Graphics和Logging窗口实战技巧,帮助工程师高效分析总线故障。通过智能过滤、可视化监控和智能日志管理,构建系统级问题定位工作流,显著提升车载网络故障排查效率。

weixin_42709044的博客 293

深入剖析 I/O 复用之 select 机制

由于 `select` 存在一些局限性,它适用于文件描述符数量较少、对性能要求不是特别高的场景,例如一些简单的网络服务器、嵌入式系统等。在实际应用中,若需要处理大量文件描述符或对性能有更高要求,可以考虑使用 `poll` 或 `epoll` 等更高级的 I/O 复用机制。 通过深入理解 `select` 的原理、使用方法和优缺点,我们能够在网络编程中更好地运用这一技术,构建高效稳定的网络应用。

w20010915的博客 1006

手把手教你学simulink--永磁同步电机场景实例:使用Simulink进行PMSM的矢量控制仿真

矢量控制的重要性提高效率:通过精确控制磁场方向,可以优化电机的工作状态,减少损耗。增强动态性能:矢量控制能够快速响应负载变化,提供更好的调速性能。简化设计:将复杂的交流电机控制问题转化为类似直流电机的控制问题,便于设计和实现。通过上述步骤,我们简要介绍了如何基于Simulink实现PMSM的矢量控制仿真。

MHD0815的博客 420

IO/多路复用(select/poll/epoll)

五种基本的IO模型 为什么需要IO多路转接呢? 三种IO转接模型的优缺点 select/poll/epoll

一个计算机爱好者学习历程 1400

【数据集】3D-GloBFP:全球首个三维建筑轮廓数据集

【数据集】3D-GloBFP:全球首个三维建筑轮廓数据集

WW、forever的博客 1689

【微服务】SpringBoot 整合Kafka 项目实战操作详解

SpringBoot 整合Kafka 实战操作详解

congge 5571

LINUX文件描述符集合详解

它允许程序同时监控多个文件描述符(如套接字、管道、文件等),并在它们可读、可写或发生异常时高效地处理 I/O 操作。在 Unix/Linux 系统中,每个打开的文件、套接字、管道等都会分配一个。是一种数据结构,用于存储一组文件描述符,以便系统调用(如。)可以同时监控它们的 I/O 状态(可读、可写、异常)。是最早的 I/O 多路复用机制,它使用。)是 Unix/Linux 系统中用于。的局限性,现代程序更倾向于使用。来监控多个文件描述符的状态。:适合少量文件描述符的监控。,它是一个非负整数(如。

niuTyler的博客 1129

工业视觉实战:用摄像头+AI高精度测量钢板尺寸(附深度分析)

摘要: 钢铁制造业正加速采用基于摄像头与深度学习的视觉测量技术,以取代传统人工测量,实现钢板长、宽、高(厚)的非接触、高精度在线检测。核心方案包括单目视觉(低成本但受限于变形)、双目/多目立体视觉(可精确测量变形钢板)及3D激光扫描(微米级精度)。系统精度受硬件(相机分辨率、镜头)、算法(亚像素技术)及环境稳定性共同影响,综合精度可达±0.1mm。实战中需重点解决热膨胀(需红外测温实时补偿)和钢板变形(必须采用三维方案)两大挑战,并通过工程化设计(散热、防振)确保系统可靠运行。该技术需融合光学、机械与算法,

数字人生 391

Select()系统调用及文件描述符集fd_set的应用 .

Select()系统调用及文件描述符集fd_set的应用在网络程序中,一个进程同时处理多个文件描述符是很常见的情况。select()系统调用可以使进程检测同时等待的多个I/O设备,当没有设备准备好时,select()阻塞,其中任一设备准备好时,select()

sunxx1986的专栏 904

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Linux - Select()系统调用及文件描述符集fd_set的应用

select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成,当调用select()时,由内核根据IO状态修改fe_set的内容,由此来通知执行了select()的进程哪一socket或文件可读。     多端口复用函数select在调用前要首

jiangxinyu的专栏 4355

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

上一篇: Java 中 对 象 的 序 列 化 技 术
下一篇: Linux服务器集群系统(一)
juvencoco
博客等级 码龄25年 2粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值