superponer - ¿Cómo implementar un tiempo de espera en la llamada de función de lectura?
superponer graficas en r (5)
Como alternativa a select()
, para el caso específico de un puerto serie (terminal) puede usar tcsetattr()
para poner el descriptor de archivo en modo no canónico, con un tiempo de espera de lectura.
Para hacer esto, desactive la bandera de ICANON
y configure el caracter de control de VTIME
:
struct termios termios;
tcgetattr(filedesc, &termios);
termios.c_lflag &= ~ICANON; /* Set non-canonical mode */
termios.c_cc[VTIME] = 100; /* Set timeout of 10.0 seconds */
tcsetattr(filedesc, TCSANOW, &termios);
Nota: VTIME
se mide en décimas de segundo, y que el tipo utilizado para ello suele ser un unsigned char
, lo que significa que el tiempo máximo de espera es de 25,5 segundos.
Quiero utilizar el puerto serie com para la comunicación y quiero implementar un tiempo de espera cada vez que llamo a la llamada de función de lectura.
int filedesc = open( "dev/ttyS0", O_RDWR );
read( filedesc, buff, len );
EDITAR:
Estoy usando el sistema operativo Linux. ¿Cómo implementar usando la llamada de función de selección?
Linux considera dos tipos de dispositivos. "Lento" (por ejemplo, red) y "rápido" (por ejemplo, disco). El modo sin bloqueo es para dispositivos "lentos", no "rápidos". Bloquee los dispositivos como supuestamente "rápidos", de modo que select / poll siempre diga que están listos para E / S. Para algunos dispositivos flash, esto es una mentira y he visto algunas llamadas de E / S que usan varios segundos para algunos bytes, incluso si select / poll dice que el dispositivo está listo. Dicho esto, incluso para dispositivos lentos, no hay una garantía fuerte sobre el retraso de lectura; Si proporciona un búfer lo suficientemente grande y los datos están disponibles (ha utilizado Select o Poll para asegurarse de eso), la llamada de lectura puede usar una gran cantidad de tiempo (cientos de ms en la red).
No dice qué es el sistema operativo, pero si se ejecuta bajo Linux, podría usar la llamada de selección. Se devuelve si hay algo para leer en el descriptor de archivo o puede configurarlo para que se agote el tiempo de espera si no hay nada que leer. El código de retorno indica cual.
Si configura el socket, opere en modo no bloqueante, cada llamada para leer solo leerá los datos actualmente disponibles (si los hay). Entonces esto es efectivamente igual a un tiempo de espera inmediato.
Puede establecer el modo sin bloqueo en un socket con una función como esta:
int setnonblock(int sock) {
int flags;
flags = fcntl(sock, F_GETFL, 0);
if (-1 == flags)
return -1;
return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}
(Para obtener más información sobre la lectura de los sockets que no sean de bloqueo, consulte la página de read
hombre)
select () toma 5 parámetros, primero el descriptor de archivo más alto + 1, luego un fd_set para lectura, uno para escritura y uno para excepciones. El último parámetro es un struct timeval, utilizado para el tiempo de espera. Devuelve -1 en error, 0 en tiempo de espera o el número de descriptores de archivo en los conjuntos que se establecen.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
int main(void)
{
fd_set set;
struct timeval timeout;
int rv;
char buff[100];
int len = 100;
int filedesc = open( "dev/ttyS0", O_RDWR );
FD_ZERO(&set); /* clear the set */
FD_SET(filedesc, &set); /* add our file descriptor to the set */
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
rv = select(filedesc + 1, &set, NULL, NULL, &timeout);
if(rv == -1)
perror("select"); /* an error accured */
else if(rv == 0)
printf("timeout"); /* a timeout occured */
else
read( filedesc, buff, len ); /* there was data to read */
}