我用read_fds中的一個命名管道fd調用select。這個命名管道沒有寫入器,只能以非阻塞,只讀模式打開。我期望與命名管道FD選擇返回標記爲準備好讀,而且試圖從管道返回0閱讀:爲什麼在沒有寫入程序的命名管道上選擇無限期地阻塞?
從上讀手冊頁:
當試圖從閱讀空管道或FIFO:
- 如果沒有進程打開管道,read()應該返回0來指示文件結束。
但是,選擇只是無限地阻止。爲什麼會這樣?
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdexcept>
#include <thread>
#include <iostream>
int main()
{
char buf[4096];
// Create a named pipe
auto err = mkfifo("/tmp/whatever",0666);
if(err) {
throw std::runtime_error(
std::string("Failed to create fifo ")+
strerror(errno));
}
std::thread reader_thread(
[&](){
auto fd = open("/tmp/whatever",O_RDONLY|O_NONBLOCK);
if(fd < 0) {
throw std::runtime_error("Failed to open fifo");
}
fd_set fds;
while(1) {
FD_ZERO(&fds);
FD_SET(fd,&fds);
std::cerr << "calling select" << std::endl;
auto retval = select(fd+1,&fds,nullptr,nullptr,nullptr);
if(retval < 0) {
std::runtime_error("Failed to call select");
}
if(FD_ISSET(fd,&fds)) {
auto read_bytes = read(fd,buf,4096);
std::cerr << "read " << read_bytes << std::endl;
if(read_bytes==0) {
break;
}
}
}
close(fd);
});
reader_thread.join();
return 0;
}
不要垃圾郵件標籤! C不是C++不是C! – Olaf
爲什麼要選擇'返回,如果沒有什麼可讀? – Olaf
@Olaf>因爲select的手冊頁明確指出*「一個文件描述符也在文件結束時準備就緒」*而fifo手冊頁也表示*「如果所有文件描述符指向管道的寫入結束已關閉,那麼嘗試從管道讀取(2)將看到文件結尾「*」。這實際上是個好問題。 – spectras