Tabla de contenido
Tres, el proceso de realización
1. Señal
Revisemos primero la "interrupción". La interrupción es un mecanismo asincrónico proporcionado por el procesador. Después de configurar la interrupción, podemos dejar que el procesador se encargue de otras cosas. Cuando ocurre la interrupción, activará la función de servicio de interrupción que establecimos de antemano. , Realizar un procesamiento específico en la función de servicio de interrupción. Después de que se usa la interrupción, el procesador no necesita verificar si el botón está presionado en todo momento, porque la interrupción se activará automáticamente después de presionar el botón.
Del mismo modo, las aplicaciones de Linux pueden acceder al dispositivo de disco de dos formas: bloqueando o sin bloquear
- En el modo de bloqueo, la aplicación estará en estado inactivo, esperando que el dispositivo de accionamiento esté disponible para su uso.
- En el modo sin bloqueo, sondeará continuamente a través de la función de encuesta para comprobar si se puede utilizar el archivo del dispositivo de la unidad.
La señal es similar a la "interrupción" utilizada en nuestro hardware, pero la señal está a nivel de software. Se puede considerar como una simulación de interrupción a nivel de software. El controlador puede informar que es accesible enviando activamente una señal al programa de aplicación. Una vez que el programa de aplicación obtiene la señal, puede leer o escribir datos desde el dispositivo de accionamiento . Todo el proceso es equivalente a que el programa de aplicación recibe una interrupción enviada por el controlador, y luego el programa de aplicación responde a la interrupción. Durante todo el proceso, el programa de aplicación no pregunta si el dispositivo de la unidad es accesible, todo lo dice el dispositivo de la unidad. Para la aplicación.
El núcleo de la notificación asincrónica es la señal. Todas las señales soportadas por Linux se definen en el archivo arch / xtensa / include / uapi / asm / signal.h . Estas señales son las siguientes:
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGIO 29
#define SIGPOLL SIGIO
/*
#define SIGLOST 29
*/
#define SIGPWR 30
#define SIGSYS 31
#define SIGUNUSED 31
/* These should not be considered constants from userland. */
#define SIGRTMIN 32
#define SIGRTMAX _NSIG
#define SIGSWI 32
En segundo lugar, la conexión y la diferencia entre IO síncrona, IO asíncrona, IO de bloqueo y IO sin bloqueo
https://www.cnblogs.com/euphie/p/6376508.html
Tres, el proceso de realización
Código fuente completo del controlador: https://github.com/denghengli/linux_driver/tree/master/17_fasync
1. Aplicación
Para usar la notificación asincrónica en su aplicación, debe agregar contenido:
(1) Registrar nueva función de procesamiento de números
(2) Dígale al kernel el número de proceso de esta aplicación
(3) Activar la notificación asincrónica
static void sigio_signal_func(int signum)
{
...
}
/*
*argc 应用程序参数个数
*argv 具体的参数内容,字符串形式
*/
int main(int argc, char *argv[])
{
...
signal(SIGIO, sigio_signal_func);/*设置sigio的处理函数*/
/*int fcntl (int __fd, int __cmd, ...);*/
fcntl(fd, F_SETOWN, getpid());/*设置当前进程接收SIGIO信号*/
flags = fcntl(fd, F_GETFL);/*获取当前文件标志*/
fcntl(fd, F_SETFL, flags | FASYNC);/*设置当前文件标志,开启异步通知*/
...
return 0;
}
2. Conductor
(1) Cuando se puede acceder al dispositivo, el controlador debe enviar una señal a la aplicación a través de la función kill_fasync , que equivale a generar una "interrupción"
void kill_fasync (struct fasync_struct ** fp, int sig, int band)
fp : fasync_struct que se va a operar.
sig la señal a enviar.
Se establece en POLL_IN cuando la banda es legible y se establece en POLL_OUT cuando se puede escribir.
Valor de retorno : Ninguno.
(2) Escriba la función fasync. Cuando la aplicación cambia el indicador fasync a través de fcntl (fd, F_SETFL, flags | FASYNC) , la función fasync en el conjunto de operaciones file_operations del controlador se ejecutará y la estructura de control fasync debe inicializarse en esta función
/* key设备结构体 */
struct key_dev{
...
/*异步结构体 --- 异步通知*/
struct fasync_struct *fasync_queue;
};
/*定时器回调函数*/
static void timer_func(unsigned long arg)
{
struct key_dev *dev = (struct key_dev*)arg;
...
if (dev->fasync_queue){ /*有效的按键过程,相应层发送信号实现异步通知*/
/*SIFIO为发送的信号,POLL_IO表示可读,POLL_OUT表示可写*/
kill_fasync(&dev->fasync_queue, SIGIO, POLL_IN);
}
}
}
static int key_release(struct inode *inode, struct file *filp)
{
int i = 0;
struct key_dev *dev = filp->private_data;
...
/*删除fasync结构体*/
return fasync_helper(-1, filp, 0, &dev->fasync_queue);
}
static int key_fasync(int fd, struct file *filp, int on)
{
struct key_dev *dev = filp->private_data;
/*初始化fasync结构体*/
return fasync_helper(fd, filp, on, &dev->fasync_queue);
}
/* 设备操作函数 */
static struct file_operations key_fops = {
...
.fasync = key_fasync,
};