Wykonuję długo działające (i często blokowane) polecenie przez popen(): "ls -R /"Dlaczego występuje wbudowane opóźnienie podczas czytania z popen()?
Problem: popen() wczytuje się do bufora, który dostarczasz i pozornie próbuje zapełnić CAŁKOWITY bufor przed powrotem. Powoduje to, że blokuje się dość często (jeśli twój bufor jest duży).
Wydaje się, że rozwiązaniem byłoby uniemożliwić blokowanie się dysku LDD. Kiedy to robię, popen() nadal blokuje, zwykle około 1 sekundy za każdym razem. Dlaczego to się dzieje?
Oto mój kod. Upewnij się, aby skompilować z -std = C++ 11:
#include <cstdio>
#include <iostream>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
static constexpr size_t SIZE = 65536;
struct Time
{
friend std::ostream &operator<<(std::ostream &os, Time const &t)
{
(void)t;
timeval tv;
gettimeofday(&tv, nullptr);
os << tv.tv_sec << "." << std::fixed << tv.tv_usec << " ";
return os;
}
};
int main()
{
FILE *file;
file = popen("ls -R /", "r");
if(!file)
{
std::cerr << "Could not open app: " << errno;
return -1;
}
// Make it non-blocking
int fd = fileno(file);
fcntl(fd, F_SETFL, O_NONBLOCK);
char buffer[SIZE];
Time t;
while(true)
{
int rc = fread(buffer, 1, SIZE, file);
if(rc <= 0)
{
if(EAGAIN == errno)
{
usleep(10);
continue;
}
std::cerr << t << "Error reading: " << errno << std::endl;
break;
}
std::cerr << t << "Read " << rc << std::endl;
}
pclose(file);
return 0;
}
Output (zauważ, że są one około 1 sekundy od siebie, mimo że fd jest nonblocking i mam tylko pauza 10ms w pętli):
1429625100.983786 Read 4096
1429625101.745369 Read 4096
1429625102.426967 Read 4096
1429625103.185273 Read 4096
1429625103.834241 Read 4096
1429625104.512131 Read 4096
1429625105.188010 Read 4096
1429625105.942257 Read 4096
1429625106.642877 Read 4096
Wyskakuje z "ls -R /", więc z powodu aktywności dysku wystąpi pewne opóźnienie. FWIW w moim systemie generalnie widzę znacznie mniejsze opóźnienie między odczytami z tym samym kodem. – davmac
Wypróbuj piping z 'yes' i zobacz, co się stanie. – Xaqq
Myślę, że twoje pytanie mogłoby być lepiej sformułowane. "popen() czyta do bufora, który podajesz" - nie, nie, po prostu otwiera fajkę. Czytasz z niego osobno. "popen() wciąż blokuje" - to nie jest "popen", który blokuje, to jest odczyt. – davmac