select函数和stdio不能混用
- stdio和系统IO的区别:
stdio : 在用户空间和内核空间都留有缓冲区;
系统IO : 只在内核空间留有缓冲区; - select函数只对于内核缓冲区判断读写就绪。
实验过程:
- stdio测试
//stdio
#include<iostream>
#include<sys/select.h>
#include<unistd.h>
using namespace std;
const size_t BUFFSIZE = 3;
int main()
{
fd_set readSet;
FD_ZERO(&readSet);
size_t count = 0;
while (true)
{
FD_SET(fileno(stdin), &readSet);
select(fileno(stdin) + 1, &readSet, nullptr, nullptr, nullptr);
char buff[BUFFSIZE];
cin >> buff;
cout << "Standard input! ---" << ++count << endl;
}
return 0;
}
运行结果:
分析:
输入12345464465\n
时,输入描述符就绪,读入时将12345464465\n
,从内核缓冲区读入到用户缓冲区中,然后用户缓冲区中的数据123
流向buff
中,其余数据留在用户缓冲区中,此时内核缓冲区的数据因为已经流向了用户缓冲区中,所以输入描述符未就绪,select
函数等待。因此,stdio
和select
混用会造成数据丢失。
- 系统IO测试
//systemIO
#include<iostream>
#include<sys/select.h>
#include<unistd.h>
using namespace std;
constexpr size_t BUFFSIZE = 3;
int main()
{
fd_set readSet;
FD_ZERO(&readSet);
size_t count = 0;
while (true)
{
FD_SET(fileno(stdin), &readSet);
select(fileno(stdin) + 1, &readSet, nullptr, nullptr, nullptr);
cout << "Standard input! ---" << ++count << endl;
char buff[BUFFSIZE];
read(fileno(stdin), buff, BUFFSIZE);
}
return 0;
}
运行结果:
分析:
- 输入
12345464465\n
时,输入描述符就绪,BUFFSIZE
为 3,因此读入123
,向屏幕打印一条信息,此时内核缓冲区剩下45464465\n
,输入描述符就绪,因此读入454
,向屏幕打印一条信息。然受内核缓冲区剩下64465\n
,分为两批进行输入,最终完成所有数据传输。