文档章节

linux的I/O多路转接select的fd_set数据结构和相应FD_宏的实现分析

Blacknc
 Blacknc
发布于 2014/03/24 21:57
字数 605
阅读 1351
收藏 1

在linux实现中,首先为长整形声明别名__fd_mask

1
typedef long  int    __fd_mask;

定义系统长整形的位数__NFDBITS

1
#define __NFDBITS ( 8  *(  int  )sizeof(__fd_mask))

定义fd_set结构能包含的描述符的最大个数__FD_SETSIZE

1
#define __FD_SETSIZE  1024

然后就可以定义fd_set结构了

1
2
3
4
5
6
7
8
9
10
typedef struct
         {
#ifdef __USE_XOPEN
    __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
#define __FDS_BITS( set ) ((s et )->fds_bits)
#     else
         __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
#define __FDS_BITS( set ) (( set )->__fds_bits)
#endif
         } fd_set ;

由数组fds_bits[__FD_SETSIZE / __NFDBITS]的定义可以看出,它将数组fds_bits的长度从通常的__FD_SETSIZE缩短到了(__FD_SETSIZE / __NFDBITS),数组的元素的每个位表示一个描述符,那么一个元素就可以表示__NFDBITS个描述符,整个数组就可以表示(__FD_SETSIZE / __NFDBITS)* __NFDBITS = __FD_SETSIZE个描述符了。

__FDS_BITS的定义是为了便于直接引用该结构中的fds_bits,而不用关心内部具体的定义。


关于FD_宏的定义

1
2
3
4
#define FD_SET(fd, fdsetp)     __FD_SET(fd,fdsetp)
#define FD_CLR(fd, fdsetp)     __FD_CLR(fd,fdsetp)
#define FD_ISSET(fd, fdsetp)   __FD_ISSET(fd,fdsetp)
#define FD_ZERO(fdsetp)        __FD_ZERO(fdsetp)

对于__FD_SET宏的定义

1
2
#define __FD_SET(d, set ) \
         (( void ) (__FDS_BITS( set )[__FD_ELT(d)] |= __FD_MASK(d)))

__FDS_BITS(set)引用了结构set内部的的相应的数组名,如((set) -> fds_bits)

而其中的__FD_ELT的定义

1
#define __FD_ELT(d)  ((d) / __NFDBITS )

表示描述符d应该包含在数组fds_bits的第几个元素内;

__FD_MASK宏的定义

1
#define __FD_MASK(d) ((__fd_mask) 1  << ((d) % __NFDBITS))

表示描述符d在数组相应元素的第几位;

  

这样看来,在宏__FD_SET中,__FDS_BITS(set)[__FD_ELT(d)] |= __FD_MASK(d) 就把描述符d在结构set的内部数组fd_mask的相应的元素的相应位进行了设置。


对于其他的宏的具体定义如下,分析同上

1
2
3
4
5
6
7
8
9
10
11
#define __FD_CLR(d, set ) (( void ) (__FDS_BITS( set )[__FD_ELT(d)] &= ~__FD_MASK(d)))
 
#define __FD_ISSET(d, set ) ((__FDS_BITS( set )[__FD_ELT(d)] & __FD_MASK(d)) !=   0 )
 
#define __FD_ZERO( set ) \
         do  {
             unsigned  int       __i;
             fd_set * __arr = ( set );
             for  ( __i =  0 ; __i < sizeof(fd_set) / sizeof (__fd_mask); ++__i)
                 __FDS_BITS (__arr)[__i] =  0     ;
         while  ( 0 );


© 著作权归作者所有

Blacknc
粉丝 2
博文 1
码字总数 605
作品 0
昌平
程序员
私信 提问
Linux系统文件I/O编程(三)---I/O多路复用

多路复用 函数说明 我们都知道fcntl()函数解决了文件共享的问题,如果不知道请看:http://blog.csdn.net/mybelief321/article/details/8993138。接下来该处理I/O复用的情况了。那么,什么是I...

长平狐
2013/06/17
698
0
epoll和select区别

原文出处:http://blog.csdn.net/ysu108/article/details/7570571 先说下本文框架,先是问题引出,然后概括两个机制的区别和联系,最后介绍每个接口的用法 一、问题引出 联系区别 问题的引出...

long0404
2015/06/17
0
0
select 和 epoll 多路复用IO

先说下本文框架,先是问题引出,然后概括两个机制的区别和联系,最后介绍每个接口的用法 一、问题引出 联系区别 问题的引出,当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长...

songzhongping
2013/08/09
1K
0
Socket编程模式理解与对比

本文主要分析了几种Socket编程的模式。主要包括基本的阻塞Socket、非阻塞Socket、I/O多路复用。其中,阻塞和非阻塞是相对于套接字来说的,而其他的模式本质上来说是基于Socket的并发模式。I...

xumaojun
2018/05/01
0
0
Linux的I/O多路复用机制之--select&poll

1. Linux下的五种I/O模型 1)阻塞I/O(blocking I/O) 2)非阻塞I/O (nonblocking I/O) 3) I/O复用(select 和poll) (I/O multiplexing) 4)信号驱动I/O (signal driven I/O (SIGIO)) 5)异......

duanjiatao
2016/08/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Go 关闭 channel 的 close 方法

在 Go 中我们所以 close() 来关闭一个 channel 官方的注释如下 The close built-in function closes a channel, which must be either bidirectional or send-only. It should be executed o......

mickelfeng
20分钟前
3
0
语音转文字什么方法比较简单

在很多时候一些比较重要的对话需要录制下来,在录制完成后还需要整理出文字,可是长时间的录音内容想要整理出文字是非常的麻烦的。需要花费大量的时间将录制的声音转换成文字,那么想要简单快...

401恶户
23分钟前
5
0
IIS7配置thinkphp5项目到public目录下

有个项目,tp5写的,要配置到项目的public目录下,一开始报错了...后面删除了配置,重新配置成功了,记录一下过程 1.首先,将网站根目录变为你的public目录下 2.添加解析程序的CGI,这里选择你需要解...

老bia同学
27分钟前
10
0
Redis主从复制的配置和实现原理

Redis的持久化功能在一定程度上保证了数据的安全性,即便是服务器宕机的情况下,也可以保证数据的丢失非常少。通常,为了避免服务的单点故障,会把数据复制到多个副本放在不同的服务器上,且...

TurboSanil
29分钟前
8
0
counsul 集群

1 master节点 cat << EOF > /lib/systemd/system/consul.service[Unit]Description=consul-masterAfter=network-online.target [Service]ExecStart=/bin/sh -c 'consul agent ......

拜了个拜
30分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部