select函数简单用法例程

在《The Linux Programming Interface》的 63.2.1 The select() System Call中讲述了 select() 函数的用法

下面是原型:

1 #include <sys/time.h> /* For portability */
2 #include <sys/select.h>
3 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
4 struct timeval *timeout);
5
6 Returns number of ready file descriptors, 0 on timeout, or –1 on error

其中 $readfds, $writefds, $exceptfds分别是交给select监控的读, 写, 异常文件描述符, timeout指定了监控的时间段,

即在timeout的时间段内, 如果有设定的文件描述符设备就绪, 则立即返回, 否则超时后不再监控设定的设备.

The $nfds argument must be set one greater than the highest file descriptor
number included in any of the three file descriptor sets. This argument allows
select() to be more efficient, since the kernel then knows not to check whether file
descriptor numbers higher than this value are part of each file descriptor set.

对应的操作文件描述符与文件描述符集合之间关系的宏有4个:

1 #include <sys/select.h>
2 void FD_ZERO(fd_set *fdset);
3 void FD_SET(int fd, fd_set *fdset);
4 void FD_CLR(int fd, fd_set *fdset);
5 int FD_ISSET(int fd, fd_set *fdset);
6     Returns true (1) if fd is in fdset, or false (0) otherwise

$FD_ZERO() initializes the set pointed to by fdset to be empty.
$FD_SET() adds the file descriptor fd to the set pointed to by fdset.
$FD_CLR() removes the file descriptor fd from the set pointed to by fdset.
$FD_ISSET() returns true if the file descriptor fd is a member of the set pointed to
by fdset.

以下是书中的示例代码:

 1 /************************************************************************* 2 *                  Copyright (C) Michael Kerrisk, 2015.                   *
 3 *                                                                         *
 4 * This program is free software. You may use, modify, and redistribute it *
 5 * under the terms of the GNU General Public License as published by the   *
 6 * Free Software Foundation, either version 3 or (at your option) any      *
 7 * later version. This program is distributed without any warranty.  See   *
 8 * the file COPYING.gpl-v3 for details.                                    *
 9 \*************************************************************************/
10
11 /* Listing 63-1 */
12
13 /* t_select.c
14
15    Example of the use of the select() system call to monitor multiple
16    file descriptors.
17
18    Usage as shown in usageError().
19 */
20 #include <sys/time.h>
21 #if ! defined(__hpux)
22 /* HP-UX 11 doesn‘t have this header file */
23 #include <sys/select.h>
24 #endif
25 #include "tlpi_hdr.h"
26
27 static void
28 usageError(const char *progName)
29 {
30     fprintf(stderr, "Usage: %s {timeout|-} fd-num[rw]...\n", progName);
31     fprintf(stderr, "    - means infinite timeout; \n");
32     fprintf(stderr, "    r = monitor for read\n");
33     fprintf(stderr, "    w = monitor for write\n\n");
34     fprintf(stderr, "    e.g.: %s - 0rw 1w\n", progName);
35     exit(EXIT_FAILURE);
36 }
37
38 int
39 main(int argc, char *argv[])
40 {
41     fd_set readfds, writefds;//读, 写文件描述符
42     int ready, nfds, fd, numRead, j;
43     struct timeval timeout;//超时
44     struct timeval *pto;
45     char buf[10];                       /* Large enough to hold "rw\0" */
46
47     if (argc < 2 || strcmp(argv[1], "--help") == 0)
48         usageError(argv[0]);
49
50     /* Timeout for select() is specified in argv[1] */
51
52     if (strcmp(argv[1], "-") == 0) {
53         pto = NULL;                     /* Infinite timeout */
54     } else {
55         pto = &timeout;
56         timeout.tv_sec = getLong(argv[1], 0, "timeout");
57         timeout.tv_usec = 0;            /* No microseconds */
58     }
59
60     /* Process remaining arguments to build file descriptor sets */
61
62     nfds = 0;
63     FD_ZERO(&readfds);
64     FD_ZERO(&writefds);
65
66     for (j = 2; j < argc; j++) {
67         numRead = sscanf(argv[j], "%d%2[rw]", &fd, buf);//将文件描述符输入fd, 将输入/输出参数写入buf[]
68         if (numRead != 2)
69             usageError(argv[0]);
70         if (fd >= FD_SETSIZE)
71             cmdLineErr("file descriptor exceeds limit (%d)\n", FD_SETSIZE);
72
73         if (fd >= nfds)
74             nfds = fd + 1;              /* Record maximum fd + 1 */
75         if (strchr(buf, ‘r‘) != NULL)
76             FD_SET(fd, &readfds);
77         if (strchr(buf, ‘w‘) != NULL)
78             FD_SET(fd, &writefds);
79     }
80
81     /* We‘ve built all of the arguments; now call select() */
82
83     ready = select(nfds, &readfds, &writefds, NULL, pto);
84                                         /* Ignore exceptional events */
85     if (ready == -1)
86         errExit("select");
87
88     /* Display results of select() */
89
90     printf("ready = %d\n", ready);
91     for (fd = 0; fd < nfds; fd++)
92         printf("%d: %s%s\n", fd, FD_ISSET(fd, &readfds) ? "r" : "",
93                 FD_ISSET(fd, &writefds) ? "w" : "");
94
95     if (pto != NULL)
96         printf("timeout after select(): %ld.%03ld\n",
97                (long) timeout.tv_sec, (long) timeout.tv_usec / 1000);
98     exit(EXIT_SUCCESS);
99 }

附件是书的代码包: 链接: http://pan.baidu.com/s/1qWYJ54w 密码: wmqb

时间: 2024-10-14 04:55:28

select函数简单用法例程的相关文章

WinSocket的select函数的用法(windows套接字比较研究)

总体上来说select函数的作用: 确定一个或多个套接口的状态,本函数用于确定一个或多个套接口的状态,对每一个套接口,调用者可查询它的可读性.可写性及错误状态信息,用fd_set结构来表示一组等待检查的套接口,在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目. 简单来说select用来填充一组可用的socket句柄,当满足下列之一条件时: 1.可以读取的sockets.当这些socket被返回时,在这些socket上执行recv/accept

select函数详细用法解析

1.表头文件 #include #include #include 2.函数原型 int select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout); 3.函数说明 select()用来等待文件描述词状态的改变.参数n代表最大的文件描述词加1,参数readfds.writefds和exceptfds 称为描述词组,是用来回传该描述词的读,写或例外的状况.底下的宏提供了处理

select函数的用法

首先介绍阻塞方式与非阻塞方式: 阻塞方式(block),就是进程或是线程执行到这些函数时必须等待某个事件的发生.如果事件没有发生,进程或线程就被阻塞,函数不能立即返回. 非阻塞方式(non-block),就是进程或线程执行函数时不必非要等待事件发生,一旦执行必定返回,以返回值的不同来反映函数的执行情况.如果事件发生,则与阻塞方式相同:如果事件没有发生,则返回一个代码告知事件未发生,而进程或线程继续执行.因而效率较高. select函数可以监视我们需要监视的文件描述符的变化情况. 下面介绍两个机构

Oracle的REGEXP_INSTR函数简单用法

REGEXP_INSTR函数让你搜索一个正则表达式模式字符串.函数使用输入字符集定义的字符进行字符串的计算. 它返回一个整数,指示开始或结束匹配的子位置,这取决于return_option参数的值.如果没有找到匹配,则函数返回0. 语法 Oracle数据库中的REGEXP_INSTR函数的语法是: REGEXP_INSTR (source_char, pattern [, position [, occurrence [, return_option [, match_parameter ] ]

Oracle的REGEXP INSTR函数简单用法

REGEXP_INSTR函数让你搜索一个正则表达式模式字符串.函数使用输入字符集定义的字符进行字符串的计算. 它返回一个整数,指示开始或结束匹配的子位置,这取决于return_option参数的值.如果没有找到匹配,则函数返回0. 语法 Oracle数据库中的REGEXP_INSTR函数的语法是: REGEXP_INSTR (source_char, pattern [, position [, occurrence [, return_option [, match_parameter ] ]

Oracle的REGEXP_SUBSTR函数简单用法

REGEXP_SUBSTR延伸SUBSTR函数的功能,让你搜索一个正则表达式模式字符串. 这也类似于REGEXP_INSTR,而是返回子字符串的位置,它返回的子字符串本身. 语法 Oracle数据库中的REGEXP_SUBSTR函数的语法是: REGEXP_SUBSTR(source_char, pattern [, position [, occurrence [, match_parameter ]]]) 参数 source_char 搜索字符串.可以是任意的数据类型char,VARCHAR

Oracle的substr函数简单用法

substr(字符串,截取开始位置,截取长度) //返回截取的字符串(包含开始位置) select substr('HelloWorld',0,3) value from dual; --返回结果为 Hel select substr('HelloWorld',1,3) value from dual; --返回结果为 Hel ,0和1都是表示从第一个字符还是截取 select substr('HelloWorld',6,5) value from dual; --返回结果为 World sel

IO复用与select函数

socket select函数的详细讲解 select函数详细用法解析      http://blog.chinaunix.net/uid-21411227-id-1826874.html

USB的固件和驱动的最简单用法

1.利用Cypress提供的USB通用驱动程序CyUSB.sys and CyUSB.inf,是稳妥的做法,因为驱动程序的编程比较繁琐,可尽力规避.可简单修改sys文件名.inf文件中的ID码.inf文件中出现的sys文件的文件名: 2.在一个EZUSB固件工程中,一般只需要修改两个文件:Periph.c(用户调度函数,不同工程取名不同,如官方例程中的BulkLoop.c), DSCR.A51(USB描述符列表,通常是汇编语言编写的,读起来简单直接): 3.实际固件编程中一般只需要修改fw.c中