2012-06-25 5 views
6

Tengo un controlador de dispositivo de caracteres de Linux que crea una entrada /dev/mything, y luego un programa C++/Qt que abre el dispositivo y lo usa. Si ese programa sale correctamente, con exit(), el dispositivo se cierra y el controlador se reinicia correctamente. Pero si el programa se cierra de manera anormal, a través de segfault o SIGINT o algo así, el dispositivo no se cierra correctamente.¿Cómo puede detectar un controlador de dispositivo de caracteres Linux cuando un programa que lo usa sale anormalmente?

Mi solución actual es volver a cargar el controlador si se queda atascado en el estado "abierto".

Esta línea en el controlador intenta evitar que varios programas de utilizar el dispositivo de forma simultánea:

int mything_open(struct inode* inode, struct file* filp) { 
    ... 
    if (port->rings[bufcount].virt_addr) return -EBUSY; 
    ... 
} 

Entonces esto lo limpia:

int mything_release(struct inode* inode, struct file* filp) { 
    ... 
    port->rings[bufcount].virt_addr = NULL; 
    ... 
} 

creo exit() está causando mything_release ser llamado, pero SIGINT no es. ¿Cómo puedo hacer que el controlador sea más robusto para este tipo de situación?

EDIT:

Estas son las operaciones que han puesto en práctica. Tal vez me estoy perdiendo algo?

static struct file_operations fatpipe_fops = { 
    .owner = THIS_MODULE, 
    .open =  mything_open, 
    .release = mything_release, 
    .read =  mything_read, 
    .write = mything_write, 
    .ioctl = mything_ioctl 
}; 
+2

Cuando el proceso finaliza o finaliza, el kernel liberará los recursos. Incluyendo la cuenta de referencia en cualquier descriptor de archivo abierto. – wildplasser

+0

Si ese es el caso, ¿por qué después de que mi programa termina con SIGINT/segfault, obtengo 'Device or resource busy' cuando intento reabrir el programa? No veo ese error si lo salgo limpiamente y lo vuelvo a abrir. – Dave

+0

No sé tu código. ¿Tal vez tienes el valor incorrecto para el bufcount? Tal vez no has implementado una de las funciones necesarias? – wildplasser

Respuesta

1

El problema se reducía a esta línea en mything_release, puesto en esperar a que algo de memoria para completar escribe:

if (wait_event_interruptible_timeout(port->inq, false, 10)) return -ERESTARTSYS; 

Con una salida normal del programa, esto haría girar por 10 unidades de tiempo y continuar a lo largo. Pero con una salida anormal de SIGINT o algo así, creo que el tiempo de espera interrumpible se interrumpió y devolvió -ERESTARTSYS, causando que mi respuesta sea la misma.

Lo que funcionó para mí fue simplemente deshacerse de la if y sólo tiene que esperar:

wait_event_interruptible_timeout(port->inq, false, 10); 

Este parche desde hace años me hizo creer que la devolución de ERESTARTSYS de una función de cierre/_release no es un buen idea: http://us.generation-nt.com/answer/patch-fix-wrong-error-code-interrupted-close-syscalls-help-181191441.html

2

No hay necesidad de esta prueba; el problema no es la terminación anormal del programa (que, desde el punto de vista de su conductor, es exactamente como un close normal en el dispositivo) sino un problema en el mantenimiento del estado de su dispositivo. En otras palabras, si insertó close(dev_fd) o incluso exit(0) en el punto exacto en que su programa falla, usted tendría el mismo problema.

Debería averiguar qué parte del comportamiento de su controlador está causando que permanezca en estado ocupado y solucionarlo.

+0

Tomé el consejo de wildplasser, arriba, e inserté algunas llamadas de impresión en 'mything_release'. Encontré una línea que dice 'if (wait_event_interruptible_timeout (port-> inq, false, 10)) return -ERESTARTSYS;', y me di cuenta de que con terminación anormal, nunca pasa esa línea. Google me hace pensar que ERESTARTSYS no está bien para regresar de una función cercana. – Dave

Cuestiones relacionadas