Linux下的select函数怎么使用?详细讲解timeval参数含义 (linux select timeval)

Linux系统下的select函数是一种多路复用的I/O模型,可以实现同时监控多个文件描述符的功能。在网络编程中,select函数经常被用来监听socket文件描述符,从而实现非阻塞的事件循环。在本文中,我们将详细介绍Linux下select函数的使用方法,并讲解其中与时间相关的timeval参数的含义。

1. select函数的原型和基本使用方法

下面是select函数的原型:

“`

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

“`

其中nfds表示待检测的更大文件描述符值加1,readfds、writefds、exceptfds是操作文件描述符的,timeout是等待超时时间。

在select函数中,当一个文件描述符已经准备好进行I/O操作时,select函数会返回一个正整数(正整数的含义会在下一节中讲解),从而通知用户进程可以开始进行I/O操作了。如果在等待超时事件内没有任何事件发生,则select函数返回0。如果select函数检测到一个错误,比如文件描述符无效等,函数将返回-1并设置errno参数。

下面是一个简单的select函数使用的例子:

“`

#include

#include

#include

#include

int mn()

{

fd_set rfds;

struct timeval tv;

int retval;

/* Wts up to five seconds. */

tv.tv_sec = 5;

tv.tv_usec = 0;

/* Watch stdin (fd 0) to see when it has input. */

FD_ZERO(&rfds);

FD_SET(0, &rfds);

/* Use select to check if input is ready now. */

retval = select(1, &rfds, NULL, NULL, &tv);

/* Don’t trust the value of tv now! */

if (retval == -1)

perror(“select()”);

else if (retval)

printf(“Data is avlable now.\n”);

else

printf(“No data within five seconds.\n”);

return 0;

}

“`

这段代码将监控标准输入文件描述符(0号文件描述符,即stdin),并等待5秒钟。如果在5秒内有数据输入,程序将输出“Data is avlable now.”,否则输出“No data within five seconds.”。

2. timeval参数的含义

在上一节的例子中,我们创建了一个timeval结构体来表示等待时间,这个结构体中有两个成员变量:

“`

struct timeval {

time_t tv_sec; /* seconds */

suseconds_t tv_usec; /* microseconds */

};

“`

其中tv_sec表示等待时间的秒数,tv_usec表示等待时间的微秒数。

在select函数调用时,timeout参数可能有三种情况:

1. timeout的值为NULL,表示select函数在没有文件描述符准备好的情况下立即返回(非阻塞模式)。

2. timeout的值为0秒0微秒,表示select函数在检查了所有设置的文件描述符后立即返回(轮询模式)。

3. timeout的值不为0表示等待时间的长度,表示在等待这段时间后,如果依然没有文件描述符准备好,函数将返回(阻塞模式)。

需要注意的是,timeout参数是值传递而非引用传递,也就是说,当select函数返回时,timeout结构体中的值可能会被修改,因此上面的例子中要声明一个单独的timeval结构体变量,而不能直接使用tv成员变量。

3. select函数返回的值含义

select函数返回一个整型值,这个值中包含了多个信息:

1. 当select函数检测到一个文件描述符准备好进行I/O操作时,对应的文件描述符位置上的位(bit)会被置为1,这个整型值的二进制表示中,对应的位也会被置为1。比如,如果标准输入文件描述符准备好了,返回值的二进制表示中第1位就会被置为1。

2. 当select函数返回0时(也就是没有文件描述符准备好),表示按照timeout参数设置的时间内没有事件发生,所以select函数返回0。

3. 如果select函数在执行过程中出现了错误,会返回-1并设置errno参数,表示出现了一个系统错误。

因此,在使用select函数时,我们需要根据返回值的不同情况来执行不同的操作。

4.

相关问题拓展阅读:

linux下,记录响应时间的脚本,精确到毫秒ms

执行前、执行后获取友枝两次时间戳相减吧。

不过 Linux 貌似服务器版、普通桌面好启敏版的时钟精确度不旁塌是很高。

gettimeofday(取得目前的时间)

相关函数

time,ctime,ftime,settimeofday

表头文件

#include

#include

定义函数

int gettimeofday ( struct timeval * tv , struct timezone * tz )

函数说明

gettimeofday()会把目前的时间有tv所指的结构返回,当地时区的信息则放判锋到tz所指的结构唤冲巧中。

timeval结构定义为:

struct timeval{

long tv_sec; /*秒*/

long tv_usec; /*微秒*/

};

timezone 结构定义为:

struct timezone{

int tz_minuteswest; /*和Greenwich 时间差了多少分钟*/

int tz_dsttime; /*日光节约时间的状态*/

};

上述两个结构都定义在/usr/include/sys/time.h。tz_dsttime 所代表的状态如下

DST_NONE /*不使用*/

DST_USA /*美国*/

DST_AUST /*澳洲*/

DST_WET /*西欧*/

DST_MET /*中欧*/

DST_EET /*东欧*/

DST_CAN /*加拿大*/

DST_GB /*大不列颠*/

DST_RUM /*罗马尼亚*/

DST_TUR /*土耳其*/

DST_AUSTALT /*澳洲(1986年以后)*/

返回值

成功则返回0,失败返回-1,错误代码存于errno。附加说明EFAULT指针tv和tz所指的内存空间超出存取权限和键。

范例

#include

#include

main(){

struct timeval tv;

struct timezone tz;

gettimeofday (&tv , &tz);

printf(“tv_sec; %d\n”, tv,.tv_sec) ;

printf(“tv_usec; %d\n”,tv.tv_usec);

printf(“tz_minuteswest; %d\n”, tz.tz_minuteswest);

printf(“tz_dsttime, %d\n”,tz.tz_dsttime);

}

执行

tv_sec:

tv_usec:136996

tz_minuteswest:-540

tz_dsttime:0

调用在返回前等待多长时间.如果timeval为,则select立即返回,这可用于探询

readfds参数标识等待可读性检查的套接口。如果该套接口正处于监听listen()状态,则若有连接请求到达,该套接口便被标识为可读,这样一个accept()调用保证可以无阻塞完成,对其他套接口而言,可读性意味着有排队数据供读取。或者对于SOCK_STREAM类型套接口来说,相对于该套接口的虚套接口已关闭,于是recv()或recvfrom()操作均能无阻塞完成,writefds参数标识等待可写性检查的套接口。如果一个套接口正在connect()连接(非阻塞),可写性意味着连接顺利建立。如果套接口并未处于connect()调用中,可写性意味着send()和sendto()调用将无阻塞完成。〔但并未指出这个保证在多长时间内有效,特别是在多线程环境中〕。

exceptfds参数标识等待带外数据存在性或意味错误条件检查的套接口,请注意如果设置了SO_OOBINLINE选项为假FALSE,则只能用这种方法来检查带外数据的存在与否,对于SO_STREAM类型套接口,远端造成的连接中止和KEEPALIVE错误都将被作为意味出错。如果套接口正在进行连接connect()(非阻塞方式),则连接试图的失败将会表现在exceptfds参数中。

如果对readfds、writefds或exceptfds中任一个组类不感兴趣,可将它置为空NULL。

在socket.h头文件定义了四个宏来操作描述字集。FD_SETSIZE变量用于确定一个中最多有多少描述字(FD_SETSIZE缺省值为64,可在包含socket.h前用#define FD_SETSIZE来改变该值)。对于内部表示,fd_set被表示成一个套接口的队列,最后一个有效元素的后续元素为INVAL_SOCKET。宏为:FD_CLR(s,*set):从set中删除描述字源搜s。FD_ISSET(s,*set):若s为中一员,非零;否则为零。FD_SET(s,*set):向添加描述字s。FD_ZERO(*set):将set初始化为空集NULL。

timeout参数控制select完成的时间。若timeout参数为空指针,则select将一直阻塞到有一个描述字满足条件,否则的话,timeout指向一个timeval结构,其中指定了select调用在返回前等待多长时间。如果timeval为{0,0},则select立即返回,这可用于探歼搏询所选套接口的状态,如果处于这种状态,则select调用氏裂祥可认为是非阻塞的,且一切适用于非阻塞调用的假设都适用于它,举例来说,阻塞钩子函数不应被调用,且套接口实现不应yield。

关于linux select timeval的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux下的select函数怎么使用?详细讲解timeval参数含义 (linux select timeval)