Linux:fd_set 结构体定义及使用

在使用select函数时,fd_set结构体是很重要的。

想正确使用select函数,理解fd_set是必不可少的。

<sys/select.h>

下面给出<sys/select.h>头文件的全部内容:

/* `fd_set' type and related macros, and `select'/`pselect' declarations.
   Copyright (C) 1996-2016 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

/*	POSIX 1003.1g: 6.2 Select from File Descriptor Sets <sys/select.h>  */

#ifndef _SYS_SELECT_H
#define _SYS_SELECT_H	1

#include <features.h>

/* Get definition of needed basic types.  */
#include <bits/types.h>

/* Get __FD_* definitions.  */
#include <bits/select.h>

/* Get __sigset_t.  */
#include <bits/sigset.h>

#ifndef __sigset_t_defined
# define __sigset_t_defined
typedef __sigset_t sigset_t;
#endif

/* Get definition of timer specification structures.  */
#define __need_time_t
#ifdef __USE_XOPEN2K
# define __need_timespec
#endif
#include <time.h>
#define __need_timeval
#include <bits/time.h>

#ifndef __suseconds_t_defined
typedef __suseconds_t suseconds_t;
# define __suseconds_t_defined
#endif


/* The fd_set member is required to be an array of longs.  */
typedef long int __fd_mask;

/* Some versions of <linux/posix_types.h> define this macros.  */
#undef	__NFDBITS
/* It's easier to assume 8-bit bytes than to get CHAR_BIT.  */
#define __NFDBITS	(8 * (int) sizeof (__fd_mask))
#define	__FD_ELT(d)	((d) / __NFDBITS)
#define	__FD_MASK(d)	((__fd_mask) (1UL << ((d) % __NFDBITS)))

/* fd_set for select and pselect.  */
typedef struct
  {
    /* XPG4.2 requires this member name.  Otherwise avoid the name
       from the global namespace.  */
#ifdef __USE_XOPEN
    __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else
    __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
  } fd_set;

/* Maximum number of file descriptors in `fd_set'.  */
#define	FD_SETSIZE		__FD_SETSIZE

#ifdef __USE_MISC
/* Sometimes the fd_set member is assumed to have this type.  */
typedef __fd_mask fd_mask;

/* Number of bits per word of `fd_set' (some code assumes this is 32).  */
# define NFDBITS		__NFDBITS
#endif


/* Access macros for `fd_set'.  */
#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)


__BEGIN_DECLS

/* Check the first NFDS descriptors each in READFDS (if not NULL) for read
   readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
   (if not NULL) for exceptional conditions.  If TIMEOUT is not NULL, time out
   after waiting the interval specified therein.  Returns the number of ready
   descriptors, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int select (int __nfds, fd_set *__restrict __readfds,
		   fd_set *__restrict __writefds,
		   fd_set *__restrict __exceptfds,
		   struct timeval *__restrict __timeout);

#ifdef __USE_XOPEN2K
/* Same as above only that the TIMEOUT value is given with higher
   resolution and a sigmask which is been set temporarily.  This version
   should be used.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int pselect (int __nfds, fd_set *__restrict __readfds,
		    fd_set *__restrict __writefds,
		    fd_set *__restrict __exceptfds,
		    const struct timespec *__restrict __timeout,
		    const __sigset_t *__restrict __sigmask);
#endif


/* Define some inlines helping to catch common problems.  */
#if __USE_FORTIFY_LEVEL > 0 && defined __GNUC__
# include <bits/select2.h>
#endif

__END_DECLS

#endif /* sys/select.h */

fd_set结构体

由上面可以看到,fd_set结构体的定义为:

/* fd_set for select and pselect.  */
typedef struct
  {
    /* XPG4.2 requires this member name.  Otherwise avoid the name
       from the global namespace.  */
#ifdef __USE_XOPEN
    __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else
    __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
  } fd_set;

其中 __fd_mask 为long int 类型,查看select.h文件第56行:

/* The fd_set member is required to be an array of longs.  */
typedef long int __fd_mask;

和select模型紧密相关的四个宏:

/* Access macros for `fd_set'.  */
#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)

<bits/select.h>

定义在<bits/select.h>头文件中,该文件内容如下:

/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#ifndef _SYS_SELECT_H
# error "Never use <bits/select.h> directly; include <sys/select.h> instead."
#endif


/* We don't use `memset' because this would require a prototype and
   the array isn't too big.  */
#define __FD_ZERO(s) \
  do {                                                                        \
    unsigned int __i;                                                         \
    fd_set *__arr = (s);                                                      \
    for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i)          \
      __FDS_BITS (__arr)[__i] = 0;                                            \
  } while (0)
#define __FD_SET(d, s) \
  ((void) (__FDS_BITS (s)[__FD_ELT(d)] |= __FD_MASK(d)))
#define __FD_CLR(d, s) \
  ((void) (__FDS_BITS (s)[__FD_ELT(d)] &= ~__FD_MASK(d)))
#define __FD_ISSET(d, s) \
  ((__FDS_BITS (s)[__FD_ELT (d)] & __FD_MASK (d)) != 0)

宏的定义如上所示。具体功能介绍,参考下面链接:

https://blog.csdn.net/starflame/article/details/7860091

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
timerfd_settime函数是一个Linux系统调用函数,用于创建并设置一个用于定时器的文件描述符。该函数需要传入timerfd文件描述符、设置定时器的参数(包括定时器到期的时间和定时器触发的时间间隔)以及flags参数。 使用该函数的步骤如下: 1. 创建一个timerfd文件描述符,可以使用系统调用函数timerfd_create来创建。 2. 定义一个struct itimerspec结构,用于设置定时器的参数。该结构包含两个成员:it_interval和it_value。it_interval表示定时器触发的时间间隔,it_value表示定时器到期的时间。 3. 调用timerfd_settime函数,将定时器参数设置到timerfd文件描述符中。 4. 读取timerfd文件描述符中的数据,当定时器到期时,该文件描述符会变为可读状态,可以使用read函数从中读取数据。 下面是一个简单的例子,演示如何使用timerfd_settime函数: ```c #include <sys/timerfd.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> int main() { int timer_fd; uint64_t exp; // 创建一个timerfd文件描述符 timer_fd = timerfd_create(CLOCK_MONOTONIC, 0); if (timer_fd == -1) { perror("timerfd_create"); exit(EXIT_FAILURE); } // 设置定时器参数 struct itimerspec timer_value; timer_value.it_interval.tv_sec = 1; // 定时器触发间隔1秒 timer_value.it_interval.tv_nsec = 0; timer_value.it_value.tv_sec = 5; // 定时器5秒后到期 timer_value.it_value.tv_nsec = 0; // 设置定时器参数到timerfd文件描述符中 if (timerfd_settime(timer_fd, 0, &timer_value, NULL) == -1) { perror("timerfd_settime"); exit(EXIT_FAILURE); } // 读取timerfd文件描述符中的数据 ssize_t s = read(timer_fd, &exp, sizeof(uint64_t)); if (s != sizeof(uint64_t)) { perror("read"); exit(EXIT_FAILURE); } printf("Timer expired\n"); close(timer_fd); exit(EXIT_SUCCESS); } ``` 在上述代码中,我们创建了一个定时器,设置为5秒后到期,每隔1秒触发一次。当定时器到期时,程序会打印一条消息,然后退出。 注意,在这个例子中,我们只读取了一次timerfd文件描述符中的数据,也就是说,程序只会等待定时器到期一次。如果需要等待多次定时器到期,需要在读取完数据后重新设置定时器参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值