2010-02-08 5 views
8

Estoy usando una señal en tiempo real en Linux para recibir notificaciones de la llegada de nuevos datos en un puerto serie. Desafortunadamente, esto provoca que las llamadas de suspensión se interrumpan cuando hay señal. ¿Alguien sabe de una manera de evitar este comportamiento?Cómo evitar la interrupción de las llamadas de suspensión debido a una señal en Linux

Edit: Intenté usar una señal regular (SIGUSR1) pero sigo teniendo el mismo comportamiento.

Gracias, Joao

Respuesta

12

Desde la página de manual nanosleep:

nanosleep retrasa la ejecución del programa durante al menos el tiempo especificado en * req. La función puede regresar antes si se ha entregado una señal al proceso. En este caso, devuelve -1, establece errno en EINTR y escribe el tiempo restante en la estructura apuntada por rem, a menos que rem sea NULL. El valor de * rem se puede usar para llamar de nuevo a nanosleep y completar la pausa especificada.

+0

Voy a ir con este. Eché un vistazo dentro de las bibliotecas de POCO y su implementación de Thread :: sleep hace algo como lo describió. Gracias – jassuncao

+0

No olvide verificar la respuesta seleccionada. –

+1

No lo haré pero prefiero esperar un tiempo antes de aceptar una respuesta. – jassuncao

2

Si no desea ser interrumpido, ¿Por qué utiliza la señal en tiempo real?

En algún lugar, ya sea en la "Programación Unix Avanzada" de Rockind o en el libro de Steven, había un ejemplo de cómo falsificar esto. Tome nota del tiempo actual_t antes de comenzar su sueño. Después de que se termina el sueño, verifique que haya transcurrido el tiempo requerido y, de lo contrario, comience a dormir nuevamente. Ponga el sueño en un ciclo que calcula el tiempo para ir y duerme esa cantidad, y sale cuando ha pasado el tiempo requerido.

+0

Hay todo tipo de problemas relacionados con esto si el reloj del sistema cambia. Es por eso que POSIX proporciona funciones de reloj mucho más sofisticadas que solo la llamada 'sleep', que probablemente debería abandonarse por completo ... –

7

Puede enmascarar casi todas las señales (excepto SIGKILL) usando sigprocmask() o signal() llamadas. El primero le devolverá la máscara anterior, que puede recuperar después de sleep(). Algunos ejemplos son here. Si eso no ayuda, por favor, sea más detallado de qué señal interrumpe su sueño. Creo que, además, puedes verificar esta condición ("¿Sueño interrumpido por la señal?") Y volver a dormir.

+0

Su enlace de ejemplo está roto. – OxyDeadbeef

+0

Tener los nombres de las funciones no es difícil encontrar otros ejemplos, p. [Introducción a la programación de señales de Unix] (http://titania.ctie.monash.edu.au/signals/). –

2

Bueno, se supone que una señal en tiempo real interrumpe el sueño. Podría usar una señal que no sea en tiempo real. Otro enfoque es verificar si ha transcurrido el tiempo esperado para dormir, y si no, dormir durante el intervalo restante.

+0

Gracias por su respuesta, pero el uso de una señal regular también interrumpe las llamadas de espera. – jassuncao

5

Nuevos kernels de Linux admiten signalfd(2). Eso, junto con sigprocmask(2), es una manera muy agradable de combinar el manejo de eventos de señal e IO en una sola llamada a epoll_wait(2).

+0

Esta es una manera realmente fea y no portátil de hacer algo que es fácil de hacer con total portabilidad incluso a sistemas heredados (el truco de autopipa) o a todos los modernos sistemas conformes a POSIX (con 'pselect'). –

+3

La portabilidad es un objetivo honorable, pero no siempre el primero. –

+0

La única razón * para no * ser portátil en este caso es la optimización prematura, que es la raíz de todo mal. Hay una gran manada de proselitismo de oveja Linux 'epoll' para el rendimiento, mientras que a menos que manejes cientos de miles de descriptores de archivos a la vez, la' encuesta 'simple nunca será tu cuello de botella (y aun así seguramente no será) No bebas el koolaid. –

Cuestiones relacionadas