Chciałbym otworzyć potok używając popen()
i mieć nieblokujący dostęp "do odczytu".Non-blocking pipe using popen?
Jak mogę to osiągnąć?
(przykłady znalazłem były blokowanie/synchroniczne)
Chciałbym otworzyć potok używając popen()
i mieć nieblokujący dostęp "do odczytu".Non-blocking pipe using popen?
Jak mogę to osiągnąć?
(przykłady znalazłem były blokowanie/synchroniczne)
Instalator tak:
FILE *f = popen("./output", "r");
int d = fileno(f);
fcntl(d, F_SETFL, O_NONBLOCK);
Teraz można przeczytać:
ssize_t r = read(d, buf, count);
if (r == -1 && errno == EAGAIN)
no data yet
else if (r > 0)
received data
else
pipe closed
Kiedy” gotowe, oczyszczenie:
pclose(f);
Pan spojrzał na „Zobacz także” sekcji strony man dla popen()?
Szybkie wyszukiwanie w Google ujawniło tę stronę: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking Mówi o blokowaniu i nie blokowaniu dostępu do deskryptorów plików.
Nigdy tego nie próbowałem, ale nie rozumiem, dlaczego nie można było pobrać deskryptorów plików za pomocą funkcji fileno(), użyj funkcji fcntl(), aby ustawić opcję bez blokowania, i użyj funkcji read()/write(). Warte spróbowania.
popen()
wywołuje wewnętrznie pipe()
, fork()
, dup2()
(do punktu FDS procesu podrzędnego 0/1/2 do rur) i execve()
. Czy zastanawiałeś się nad ich użyciem? W takim przypadku można ustawić odczytaną rurę jako nieblokującą za pomocą fcntl()
.
aktualizacja: Oto przykład, tylko w celach poglądowych:
int read_pipe_for_command(const char **argv)
{
int p[2];
/* Create the pipe. */
if (pipe(p))
{
return -1;
}
/* Set non-blocking on the readable end. */
if (fcntl(p[0], F_SETFL, O_NONBLOCK))
{
close(p[0]);
close(p[1]);
return -1;
}
/* Create child process. */
switch (fork())
{
case -1:
close(p[0]);
close(p[1]);
return -1;
case 0:
/* We're the parent process, close the writable part of the pipe */
close(p[1]);
return p[0];
default:
/* Close readable end of pipe */
close(p[0]);
/* Make stdout into writable end */
dup2(p[1], 1);
/* Run program */
execvp(*argv, argv);
/* If we got this far there was an error... */
perror(*argv);
exit(-1);
}
}
Działa pięknie ... dzięki! – jldupont
potok, będący wskaźnikiem PLIKU, jest z natury zbuforowany, czy istnieje pewność, że za pomocą deskryptora pliku bezpośrednio nie przeoczysz czegoś, co zostało wciągnięte do bufora plików, czy może to być zagwarantowane tak długo, jak długo będziesz Najpierw wywołasz fget/fread/etc? – stu