Notas del estudio de desarrollo de controladores de Linux [10]: Notificación asincrónica de Linux

Tabla de contenido

1. Señal

En segundo lugar, la conexión y la diferencia entre IO síncrona, IO asíncrona, IO de bloqueo y IO sin bloqueo

Tres, el proceso de realización

1. Aplicación

2. Conductor


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

  1. En el modo de bloqueo, la aplicación estará en estado inactivo, esperando que el dispositivo de accionamiento esté disponible para su uso.
  2. 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,
};

 

 

Supongo que te gusta

Origin blog.csdn.net/m0_37845735/article/details/107307462
Recomendado
Clasificación