了解 POSIX select() 与读写fd_set
Understanding POSIX select() with read and write fd_set
对于学校项目,我们将使用文件描述符和select()在一台机器上实现并发。在程序中,我们有 RequestChannel 对象,其中包含两个文件描述符,一个用于读取,一个用于写入,用于与在执行开始时分叉的单独进程进行通信。我可以用写文件描述符做一些事情,但读取的 fds 似乎从未准备好。我可以得到一些帮助来理解select()如何与读写描述符一起工作吗?我看到的一切都在处理套接字,这在这一点上让我感到困惑,我只想了解一般文件描述符和 select()。
这是我的选择循环:
fd_set readset, writeset;
FD_ZERO(&readset);
FD_SET(JohnDoe.read_fd(), &readset);
FD_SET(JoeSmith.read_fd(), &readset);
FD_SET(JaneSmith.read_fd(), &readset);
FD_ZERO(&writeset);
FD_SET(JohnDoe.write_fd(), &writeset);
FD_SET(JoeSmith.write_fd(), &writeset);
FD_SET(JaneSmith.write_fd(), &writeset);
int maxfd = 0;
maxfd = max(maxfd, JohnDoe.read_fd());
maxfd = max(maxfd, JohnDoe.write_fd());
maxfd = max(maxfd, JoeSmith.read_fd());
maxfd = max(maxfd, JoeSmith.write_fd());
maxfd = max(maxfd, JaneSmith.read_fd());
maxfd = max(maxfd, JaneSmith.write_fd());
int numready;
int count = 0;
while (count < 10) {
numready = select(maxfd + 1, &readset, &writeset, NULL, NULL);
if (numready == -1) {
cout << "Fatal error, abortingn";
break;
}
else {
if(FD_ISSET(JohnDoe.write_fd(), &writeset)) { //write_fd() returns write file descriptor
JohnDoe.cwrite("data John Doe"); //one RequestChannel object
}
if(FD_ISSET(JoeSmith.write_fd(), &writeset)) {
JoeSmith.cwrite("data Joe Smith");
}
if(FD_ISSET(JaneSmith.write_fd(), &writeset)) {
JaneSmith.cwrite("data JaneSmith");
}
if(FD_ISSET(JohnDoe.read_fd(), &readset)) {
string s = JohnDoe.cread();
cout << "John Doe cread: " << s << "n";
}
if(FD_ISSET(JoeSmith.read_fd(), &readset)) {
string s = JoeSmith.cread();
cout << "Joe Smith cread: " << s << "n";
}
if(FD_ISSET(JaneSmith.read_fd(), &readset)) {
string s = JaneSmith.cread();
cout << "Jane Smith cread: " << s << "n";
}
}
}
您需要在每次调用select()
之前重新初始化描述符集,因为select()
修改描述符集。您可以通过在循环中使用 FD_ZERO()
/FD_SET()
或通过初始化"原型"集来执行此操作,这些"原型"集复制到传递给 select()
的集:
fd_set readset, writeset;
int maxfd = 0;
maxfd = max(maxfd, JohnDoe.read_fd());
maxfd = max(maxfd, JohnDoe.write_fd());
maxfd = max(maxfd, JoeSmith.read_fd());
maxfd = max(maxfd, JoeSmith.write_fd());
maxfd = max(maxfd, JaneSmith.read_fd());
maxfd = max(maxfd, JaneSmith.write_fd());
int numready;
int count = 0;
while (count < 10) {
FD_ZERO(&readset);
FD_SET(JohnDoe.read_fd(), &readset);
FD_SET(JoeSmith.read_fd(), &readset);
FD_SET(JaneSmith.read_fd(), &readset);
FD_ZERO(&writeset);
FD_SET(JohnDoe.write_fd(), &writeset);
FD_SET(JoeSmith.write_fd(), &writeset);
FD_SET(JaneSmith.write_fd(), &writeset);
numready = select(maxfd + 1, &readset, &writeset, NULL, NULL);
// etc...
}
是的,cjbrooks12 是正确的。有必要在 select() 系统调用之间reset the fd_set
。
充当输入/输出参数;它们由系统调用读取和修改。当 select() 返回时,这些值都已修改to reflect the set of file descriptors ready
。因此,每次调用 select() 之前,您都有to (re)initialize the fd_set
值。
并且还要使while循环无限(或增加计数器值),以便它等到读取fd准备就绪。
相关文章:
- 用C++快速读写文件
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 在一个读写器队列中,我可以用volatile替换原子吗
- C++套接字对不读/写父/子
- 如何调试读写器锁的死锁?
- 在两个线程上读/写 64 位,无互斥/锁定/原子
- Linux 挂载使用重新挂载以允许读写
- C++中读/写二进制文件
- 如何读/写或遍历 std::array 中的特定元素范围?
- 内存排序或读取-修改-写入操作,仅(读/写)内存顺序
- USB-HID 读/写(重叠)等待单个对象不返回C++
- 为什么使用_access时只读测试对读写文件有效
- Boost::Asio串行读/写打开:参数不正确
- 读/写 OpenMP 中的共享向量会减慢程序速度
- 谷歌测试读写同一文件失败
- Android USB 附件模式无法使用 libusb 与主机 PC 一起读/写
- 特定时间间隔 C++ 上的读写日志
- SQLite - C++中的多线程读写
- 如何读写Qt集合类