本文主要是介绍再次一起来玩linux select函数------可以用任何描述符号fd而不限于网络socket,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在之前的网络编程中, 我们经常提到select函数, Windows select和linux select大同小异, 下面, 我们来玩玩linux select, 直接上菜:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/time.h>
#include<sys/types.h>int main()
{struct timeval tv; // 超时时间tv.tv_sec = 10;tv.tv_usec = 500; // 注意单位是微秒fd_set rdfds;FD_ZERO(&rdfds); // 描述集初始化FD_SET(STDIN_FILENO, &rdfds); // STDIN_FILENO是标准输入, 塞入描述集int iRet = select(STDIN_FILENO + 1, &rdfds, NULL, NULL, &tv); // 第一个参数是监控句柄号+1if(iRet < 0){printf("selcet error, iRet %\n", iRet);return -1;}if(0 == iRet){printf("timeout \n");return -2;}printf("iRet = %d \n", iRet); // 在终端中, 输入, 然后按enter, 会走到这里char szBuf[10]= {0};if(FD_ISSET(STDIN_FILENO, &rdfds) ) // 监控输入描述符已经发生了改变{ printf("to read data\n");read(STDIN_FILENO, szBuf, sizeof(szBuf) - 1); // 从键盘读取输入}write(STDOUT_FILENO, szBuf, strlen(szBuf)); // 在终端中回显return 0;
}
执行程序后, 程序卡在select处, 如果用户不输入任何东西, 那么就会在10s + 500微秒的时候, select返回0. 如果用户在超时之前输入, 那么select立即返回1. 有点意思, 从这个程序可以体会到select的用途。
在linux中, select函数也可以用来做延时程序哦, 精确度为微秒。爽。
为了更好地理解上面的程序, 我们继续来看一个有趣的问题:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/time.h>
#include<sys/types.h>int main()
{struct timeval tv; // 超时时间tv.tv_sec = 10;tv.tv_usec = 500; // 注意单位是微秒fd_set rdfds;FD_ZERO(&rdfds); // 描述集初始化FD_SET(STDIN_FILENO, &rdfds); // STDIN_FILENO是标准输入, 塞入描述集FD_SET(STDOUT_FILENO, &rdfds); // STDOUT_FILENO是标准输入, 塞入描述集if(FD_ISSET(STDIN_FILENO, &rdfds) ){ printf("STDIN_FILENO is in fds 111\n");}if(FD_ISSET(STDOUT_FILENO, &rdfds) ){ printf("STDOUT_FILENO is in fds 222\n");}int iRet = select(STDIN_FILENO + 1, &rdfds, NULL, NULL, &tv); // 第一个参数是监控句柄号+1if(iRet < 0){printf("selcet error, iRet %\n", iRet);return -1;}if(0 == iRet){printf("timeout \n");}printf("iRet = %d \n", iRet); if(FD_ISSET(STDIN_FILENO, &rdfds) ){ printf("STDIN_FILENO is in fds 333\n");}if(FD_ISSET(STDOUT_FILENO, &rdfds) ){ printf("STDOUT_FILENO is in fds 444\n");}return 0;
}
运行一下, 然后什么也不要动(等10s中), 结果为:
STDIN_FILENO is in fds 111
STDOUT_FILENO is in fds 222
timeout
iRet = 0
可见, 刚开始时候, 标准输入、标准输出描述符都在描述集中。 select函数在超时时间内, 没有检测到有输入输出, 此时这两个描述集被自动清除。 我们再次运行程序, 并在10s内输入数据, 可以看到, 结果为:
STDIN_FILENO is in fds 111
STDOUT_FILENO is in fds 222
iRet = 1
STDIN_FILENO is in fds 333
可以看到, 检测到有输入后, select函数立即返回, 此时标准输入描述符仍然在描述集中, 而标准输出描述集则被清除。 有点意思。
所以, 在调用select之前, 我们通常需要把待监测的描述符号放下描述集中, 而在select后, 用FD_ISSET检查哪些描述符仍在描述集中, 那么, 这些描述集就处于就绪状态。 因此, select前后的操作均不可少。
因此, 如下试好习惯和范式:
FD_ZERO
FD_SET
select
FD_ISSET
最后要注意, 上述iRet为1表示rdfds中, 就绪的描述符总个数为1.
这篇关于再次一起来玩linux select函数------可以用任何描述符号fd而不限于网络socket的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!