一、C语言用法
-
函数模型:
int select (int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
-
相关头文件
#i nclude<sys/time.h>
#i nclude<sys/types.h>
#i nclude<unistd.h>
-
参数说明
int maxfdp:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1。
fd_set *readfds: 一组发起读请求的文件描述苻,linux中一切皆文件。
fd_set *writefds:一组发起读请求的文件描述苻。
fd_set *exceptfds: 用来监视文件错误异常
struct timeval *timeout:struct timeval *timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间。
- 相关函数
select()用来等待文件描述词状态的改变。参数n代表最大的文件描述词加1,参数readfds、writefds 和exceptfds 称为描述词组,是用来回传该描述词的读,写或例外的状况。底下的宏提供了处理这三种描述词组的方式:
FD_CLR(inr fd,fd_set* set);用来清除描述词组set中相关fd 的位
FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真
FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位
FD_ZERO(fd_set *set); 用来清除描述词组set的全部位
需要注意的地方:
1、如果在一个文件描述苻上碰到了文件结尾处,则select认为该描述苻是可读的。然后调用read,返回0。
-
实例之c语言
#include
#include
#include
#include
#include
#include
#include
int main() { int keyboard; int ret, i; char c; fd_set readfd; struct timeval timeout; keyboard = open("/dev/tty", O_RDONLY|O_NONBLOCK); assert(keyboard > 0); while(1) { timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO(&readfd); FD_SET(keyboard, &readfd); ret = select(keyboard+1, &readfd, NULL, NULL, &timeout); if(FD_ISSET(keyboard, &readfd)) { i = read(keyboard, &c, 1); if('\n' == c) continue; printf("the put is %c\n",c); if('q' == c) break; } } }
-
实例之python
#! /usr/bin/env python
import select
BLKSIZE = 20
def readwrite(fromfd,tofd):
readbuf = fromfd.read(BLKSIZE)
if readbuf:
tofd.write(readbuf)
tofd.flush
return len(readbuf)
def copyfile(fromfd1,tofd1,fromfd2,tofd2):
totalbytes = 0
if not (fromfd1 or fromfd2 or tofd1 or tofd2):
return 0
while True:
rs,ws,es = select.select([fromfd1,fromfd2],[],[])
for r in rs:
if r is fromfd1:
bytesread1 = readwrite(fromfd1,tofd1)
totalbytes += bytesread1
print "copy from1 %d bytes" % bytesread1
if r is fromfd2:
bytesread2 = readwrite(fromfd2,tofd2)
totalbytes += bytesread2
print "copy from2 %d bytes" % bytesread2
if(bytesread1 <= 0 and bytesread2 <=0): #这里需要等到最大的文件复制完
break
return totalbytes
def main():
fromfd1 = open("/etc/passwd", "r")
fromfd2 = open("/etc/fstab", "r")
tofd1 = open("/home/lirifeng/passwd","w+")
tofd2 = open("/home/lirifeng/fstab","w+")
totalbytes = copyfile(fromfd1,tofd1,fromfd2,tofd2)
print "Number of bytes copied %d" % totalbytes
return 0
if __name__ == "__main__":
main()
另有select在socket编程中的用法,见链接http://zyg0227.blog.51cto.com/1043164/554208