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