Linux select()详解
(2011-07-17 23:50:39)
标签:
杂谈
Linux select()详解 select系统调用是用来让我们的过程监视多个文件句柄(file
descriptor)的事态改变的。过程会停在select这里期待,直到被监视的文件句柄有某一个或多个发生了事态改换。
文件在句柄在Linux里许多,万一你man某个函数,在函数归来值局部说到获胜后有一个文件句柄被创立的都是的,如man
socket能够看到“On success, a file descriptor for the
new socket is returned.”而man 2
open能够看到“open() and creat() return the new file
descriptor”,其实文件句柄即便一个整数,看socket函数的声明就打听了:
int socket(int domain, int type, int protocol);
当然,我们最纯熟的句柄是0、1、2三个,0是规范输入,1是规范输出,2是规范讹谬输出。0、1、2是整数表示的,对应的FILE
*构造的表示即便stdin、stdout、stderr,0即便stdin,1即便stdout,2即便stderr。
例如下面这两段代码都是从规范输入读入9个字节字符:
#include
#include
#include
int main(int argc, char ** argv)
{
char buf[10] = "";
read(0, buf, 9);
fprintf(stdout, "%s/n", buf);
return 0;
}
#include
#include
#include
int main(int argc, char ** argv)
{
char buf[10] = "";
fread(buf, 9, 1, stdin);
write(1, buf, strlen(buf));
return 0;
}
继续上面说的select,即便用来监视某个或某些句柄的事态改变的。select函数原型如下:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set
*exceptfds, struct timeval *timeout);
函数的最后一个参数timeout显明是一个超随工夫值,其种类是struct timeval *,即一个struct
timeval构造的变量的指针,因而我们在过程里要声明一个struct timeval
tv;然后把变量tv的地址&tv递交给select函数。struct
timeval构造如下:
struct timeval {
long tv_sec;
long tv_usec;
};
第2、3、4三个参数是一样的种类: fd_set *,即我们在过程里要声明几个fd_set种类的变量,例如rdfds, wtfds,
exfds,然后把这个变量的地址&rdfds, &wtfds,
&exfds
递交给select函数。这三个参数都是一个句柄的聚集,第一个rdfds是用来保留这么的句柄的:当句柄的事态变成可读的时系统就会告诉select函数归来,同理第二个wtfds是指有句柄事态变成可写的时系统就会告诉select函数归来,同理第三个参数exfds是特异情形,即句柄上有特异情形发生时系统会告诉select函数归来。特异情形例如对手穿越一个socket句柄发来了紧迫数据。万一我们过程里只想检测某个socket是否有数据可读,我们能够这么:
fd_set rdfds;
struct timeval tv;
int ret;
FD_ZERO(&rdfds);
FD_SET(socket, &rdfds);
tv.tv_sec = 1;
tv.tv_usec = 500;
ret = select(socket + 1, &rdfds, NULL, NULL,
&tv);
if(ret < 0) perror("select");
else if(ret == 0) printf("超时/n");
else {
printf("ret=%d/n", ret);
if(FD_ISSET(socket, &rdfds)) {
recv(...);
}
}
当心select函数的第一个参数,是所有加入聚集的句柄值的最大那个值还要加1。例如我们创立了3个句柄:
int sa, sb, sc;
sa = socket(...);
connect(sa,...);
sb = socket(...);
connect(sb,...);
sc = socket(...);
connect(sc,...);
FD_SET(sa, &rdfds);
FD_SET(sb,Lumi &rdfds);
FD_SET(sc, &rdfds);
在利用select函数之前,定然要找到3个句柄中的最大值是哪个,我们等闲定义一个变量来保留最大值,获得最大socket值如下:
int maxfd = 0;
if(sa > maxfd) maxfd = sa;
if(sb > maxfd) maxfd = sb;
if(sc > maxfd) maxfd = sc;
然后调用select函数:
ret = select(maxfd + 1, &rdfds, NULL, NULL,
&tv);
同样的理由,万一我们要检测用户是否按了键盘举行输入,我们就该当把规范输入0这个句柄放到select里来检测,如下:
FD_ZERO(&rdfds);
FD_SET(0, &rdfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = select(1, &rdfds, NULL, NULL,
&tv);
if(ret < 0) perror("select");
else if(ret == 0) printf("超时/n");
else {
scanf("%s", buf);
}
将对社会生态带来宏伟的波及。
分享:
喜欢
0
赠金笔
加载中,请稍候......
评论加载中,请稍候...
发评论
登录名: 密码: 找回密码 注册记住登录状态
昵 称:
评论并转载此博文
发评论
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。