che sto eseguendo un comando di lunga durata (e spesso bloccati) tramite popen(): "ls -R /"Perché c'è un ritardo incorporato durante la lettura con popen()?
Problema: popen() legge in un buffer che si fornisce, e tenta apparentemente per popolare l'INTERO buffer prima di tornare. Questo causa il blocco abbastanza spesso (se il buffer è grande).
La soluzione sembrerebbe essere quella di rendere il sotto fd non bloccante. Quando lo faccio, popen() blocca ancora, di solito circa 1 secondo ogni volta. Perché sta succedendo?
Ecco il mio codice. Assicurati di compilare con -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;
}
di uscita (si noti che sono circa 1 secondo di distanza, anche se il fd è non bloccante e ho solo una pausa 10mS nel loop):
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
Si sta eseguendo il piping da 'ls -R /', quindi ci sarà un po 'di ritardo a causa dell'attività del disco. FWIW sul mio sistema generalmente vedo un ritardo molto più basso tra le letture con lo stesso codice. – davmac
Prova a eseguire il piping da "yes" e guarda cosa succede. – Xaqq
Penso che la tua domanda potrebbe essere formulata in modo migliore. "popen() si legge in un buffer che tu fornisci" - no, non lo fa, apre solo la pipa. Leggi da questo separatamente. "popen() blocca ancora" - non è "popen" che blocca, è la lettura. – davmac