使 std::cout 不会因 O_NONBLOCK 失败或使 stdin O_NONBLOCK 保持 stdout 阻塞?
Make std::cout do not fail with O_NONBLOCK or make stdin O_NONBLOCK keeping stdout blocking?
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
int main(){
// Make stdin non-blocking
fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
printf("stdout O_NONBLOCK is: %d\n", fcntl(STDOUT_FILENO, F_GETFL) & O_NONBLOCK);
printf("stdin O_NONBLOCK is: %d\n", fcntl(STDIN_FILENO , F_GETFL) & O_NONBLOCK);
for(int i=0; i<16; i++){
cout<<" "<<"fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er "<<endl;
}
bool cerrfail=cerr.fail(), coutfail=cout.fail();
flush(cout); flush(clog); flush(cerr);
cout.clear(); cerr.clear(); clog.clear();
cerr<<"\ncerr.fail():"<<cerrfail<<" cout.fail():"<<coutfail<<endl;
}
可能的输出:
Compiler G++ 9.3
MacOS Mojave 10.14.6
stdout O_NONBLOCK is: 4
stdin O_NONBLOCK is: 4
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo ero
cerr.fail():0 cout.fail():1
因 fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
而失败
为什么?如何修复保持 stdin 非阻塞?
更新。
为什么? 因为设置标准输入 O_NONBLOCK 也会使标准输出 O_NONBLOCK。 std::out 在其内部收到一些 ASYNC 错误代码(如 ETRYAGAIN)。
我看到两个解决方案:
- 使std::cout不会因O_NONBLOCK
而失败
- 制作 stdin O_NONBLOCK 保持 stdout 阻塞?
更新2。
该问题仅出现在 MacOS 上。不在 Linux amd64 上,也不在 Linux MIPS (Atheros) 上。
标准流不支持非阻塞文件描述符,那些超出了 C++ 标准的范围。
如果您坚持对标准流使用非阻塞文件描述符,那么您需要实现一个可以read/write 非阻塞文件描述符的流缓冲区。您可以通过派生 std::basic_streambuf
并实现其虚函数或使用出色的 Boost.Iostreams 从头开始
以大大减少您必须编写的样板代码的数量和复杂性。然后通过调用 std::basic_ios<>::rdbuf
.
将 std::cout
、std::cin
和朋友的缓冲区替换为您的特殊流缓冲区
即便如此,使用 std::istream
和 std::ostream
接口您也无法区分文件结尾和 EAGAIN
。
您可能想详细说明您要解决的问题是什么,因为您当前的解决方案会产生更多问题。
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
int main(){
// Make stdin non-blocking
fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
printf("stdout O_NONBLOCK is: %d\n", fcntl(STDOUT_FILENO, F_GETFL) & O_NONBLOCK);
printf("stdin O_NONBLOCK is: %d\n", fcntl(STDIN_FILENO , F_GETFL) & O_NONBLOCK);
for(int i=0; i<16; i++){
cout<<" "<<"fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er "<<endl;
}
bool cerrfail=cerr.fail(), coutfail=cout.fail();
flush(cout); flush(clog); flush(cerr);
cout.clear(); cerr.clear(); clog.clear();
cerr<<"\ncerr.fail():"<<cerrfail<<" cout.fail():"<<coutfail<<endl;
}
可能的输出:
Compiler G++ 9.3
MacOS Mojave 10.14.6
stdout O_NONBLOCK is: 4
stdin O_NONBLOCK is: 4
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo erouhep hv reough er
fgvbhln;j;jblhcbwnoi wiejnocje ocweo cewoj coj weoj cowejojewohewouspuweoche njwpihbeh wjo ero
cerr.fail():0 cout.fail():1
因 fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
为什么?如何修复保持 stdin 非阻塞?
更新。 为什么? 因为设置标准输入 O_NONBLOCK 也会使标准输出 O_NONBLOCK。 std::out 在其内部收到一些 ASYNC 错误代码(如 ETRYAGAIN)。
我看到两个解决方案:
- 使std::cout不会因O_NONBLOCK 而失败
- 制作 stdin O_NONBLOCK 保持 stdout 阻塞?
更新2。 该问题仅出现在 MacOS 上。不在 Linux amd64 上,也不在 Linux MIPS (Atheros) 上。
标准流不支持非阻塞文件描述符,那些超出了 C++ 标准的范围。
如果您坚持对标准流使用非阻塞文件描述符,那么您需要实现一个可以read/write 非阻塞文件描述符的流缓冲区。您可以通过派生 std::basic_streambuf
并实现其虚函数或使用出色的 Boost.Iostreams 从头开始
以大大减少您必须编写的样板代码的数量和复杂性。然后通过调用 std::basic_ios<>::rdbuf
.
std::cout
、std::cin
和朋友的缓冲区替换为您的特殊流缓冲区
即便如此,使用 std::istream
和 std::ostream
接口您也无法区分文件结尾和 EAGAIN
。
您可能想详细说明您要解决的问题是什么,因为您当前的解决方案会产生更多问题。