crear - ¿Por qué es necesario el método de la sonda en los controladores de dispositivos de Linux además de init?
como crear un driver para un dispositivo (7)
En el kernel de Linux, ¿qué hace el método de la probe()
que proporciona el controlador? ¿Qué tan diferente es de la función de init
del controlador, es decir, por qué las acciones de las funciones de la probe()
no se pueden realizar en la función de init
del controlador?
Diferentes tipos de dispositivos pueden tener funciones de sondeo (). Por ejemplo, los dispositivos PCI y USB tienen funciones de sonda ().
Si está hablando de dispositivos PCI, le recomendaría que lea el capítulo 12 de Controladores de dispositivos de Linux , que cubre esta parte de la inicialización del controlador. USB se trata en el capítulo 13.
Respuesta más corta, asumiendo PCI: la función de inicio del controlador llama a pci_register_driver()
que le da al kernel una lista de los dispositivos que puede atender, junto con un puntero a la función de la probe()
. El núcleo luego llama a la función de la probe()
del controlador una vez para cada dispositivo.
Esta función de sondeo inicia la inicialización por dispositivo: inicializa el hardware, asigna recursos y registra el dispositivo con el kernel como un bloque o dispositivo de red o lo que sea.
Eso lo hace más fácil para los controladores de dispositivos, ya que nunca necesitan buscar dispositivos o preocuparse por encontrar un dispositivo que se haya conectado en caliente. El núcleo maneja esa parte y notifica al controlador correcto cuando tiene un dispositivo para que usted maneje.
El kernel de Linux utiliza un dispositivo de hardware que coincide con un proceso de controlador de dispositivo de software . init
se llama muy temprano, y registra la función de la probe
y un nombre de dispositivo de hardware como "taiko_sound_card", al núcleo. Esto es para decirle al núcleo que "Soy un controlador sw para este dispositivo con este nombre". Cuando el kernel atraviesa dispositivos hw (árbol de dispositivos o enumeración de bus) y encuentra una coincidencia, llamará a su función de probe
registrada. Ahora su controlador de dispositivo sw posee el dispositivo hw.
Si no se encuentra un dispositivo que coincida, es posible que su sonda nunca sea llamada. Esta es la razón por la que típicamente init
es pequeño y la probe
realiza todo el trabajo de init.
El sondeo se realiza cuando se llama al método de la sonda () mediante un puntero de función dentro de una estructura que se utiliza para vincular dispositivos con datos de plataforma predeterminados o personalizados con respecto al dispositivo. los controladores utilizan mucha información sobre el dispositivo, de modo que el sondeo proporciona dicha información a los controladores cuando una entrada en el campo id_table name coincide con el nombre del dispositivo.
Init (void) // se ejecuta una vez cuando se invoca el controlador / módulo y configura las cosas para la máquina del controlador del kernel.
Probe (* pdev) // es utilizado por la máquina del controlador del kernel según sea necesario para detectar e instalar dispositivos reales
La función de los controladores xxx_init_module()
llama a pci_register_driver(struct pci_driver *drv)
al pasar la referencia a la estructura de tipo pci_driver
. struct pci_driver
es una estructura importante que todos los controladores PCI deben tener, que se inicializa con variables como el nombre de los controladores, la lista de dispositivos PCI que el controlador puede admitir, las rutinas de devolución de llamada para el subsistema central PCI.
La estructura de los controladores pci_driver tiene campos de miembros importantes que se enumeran a continuación:
name
: nombre del controlador que es único entre todos los controladores PCI en el kernel. Aparecerá bajo/sys/bus/pci/drivers
.pci_device_id
: una tabla de datos de identificación del dispositivo consiste en el tipo de chips que admite este controlador.probe
- La dirección de la funciónxxx_probe()
.remove/suspend/resume/shutdown
: dirección a la función a la que el sistema central de PCI llama cuando se quita / suspende / reanuda / apaga el dispositivo PCI respectivamente. Generalmente utilizado por las capas superiores para la gestión de la energía.
Para obtener más información sobre cómo el sondeo del controlador ejecutado desde el núcleo de PCI, consulte Linux Device Driver Init .
Dispositivos múltiples y hotplug
Está ejecutando un servidor grande con muchos aceleradores GPU conectados PICe. En algún momento, decide comprar más GPU para las ranuras gratuitas.
Si
insmod
init
, tendríamos quermmod
einsmod
el módulo. Pero eso requeriría detener todas las GPU conectadas, lo que causa un tiempo de inactividad.Con la
probe
, solo enchufamos las nuevas GPU y hacemos una nueva búsqueda.PCIe hotplug no sería posible de otro modo: https://electronics.stackexchange.com/questions/208767/does-pcie-hotplug-actually-work-in-practice
Ejemplo de dispositivo QEMU edu PCI
QEMU tiene un dispositivo PCI educativo llamado edu, que nos permite probar fácilmente cuando se llama la probe
.
Primero, necesitamos un controlador PCI de kernel de Linux mínimo, que he escrito aquí .
Podemos comenzar con el dispositivo conectado con:
-device edu
pero aún más interesante, también podemos adjuntar y eliminar el dispositivo del monitor QEMU, Ctrl + Alt + 2 en la GUI de SDL o -monitor telnet::45454,server,nowait
en CLI, con los comandos:
device_add edu
device_del edu
Si el dispositivo está conectado en el arranque:
probe
se llama tan pronto comoinsmod
al módulo.dmesg
contiene una línea de tipo:pci 0000:00:04: [1234:11e8] ...
que muestra que nuestro dispositivo fue detectado en BDF0000:00:04
.Sabemos que este es nuestro dispositivo, porque el proveedor es 0x1234 y el dispositivo id 11e8 en la fuente QEMU.
Por lo tanto, llegamos a la conclusión de que los dispositivos PCI se prueban en el arranque y se almacenan en una lista en algún lugar.
Si adjuntamos el dispositivo después del arranque desde el monitor:
no pasa nada hasta que lo hagamos
echo 1 > /sys/bus/pci/rescan
Vea también: ¿Cómo se puede forzar al kernel de Linux a enumerar el bus PCI-e?
después de volver a escanear:
Si ya lo habíamos instalado, la
probe
se llama inmediatamente.Entonces, en este caso, la
probe
ocurrió por separado deinsmod
, mostrando cómo difieren.si no lo hemos hecho: la
probe
se llama inmediatamente después deinsmod
Se llamará a @Bandicoot : probe () para asegurarse de que el dispositivo existe y la funcionalidad es correcta. Si el dispositivo no es de acoplamiento activo, la funcionalidad de la sonda () se puede poner dentro del método init (). Esto reducirá el tiempo de ejecución del controlador. huella de memoria. link PS
La sonda () ocurre al momento del inicio del dispositivo o cuando el dispositivo está conectado. Para un dispositivo de "plataforma", la función de la sonda se invoca cuando se registra un dispositivo de plataforma y su nombre coincide con el nombre especificado en el controlador del dispositivo. link PS
La función i2c_detect sondea el adaptador I2C, buscando las diferentes direcciones especificadas en la estructura addr_data. Si se encuentra un dispositivo, se llama a la función chip_detect. link PS.
Un enlace que seguramente aclarará tus dudas. link PS
En el kernel 2.4.29, puedo mostrarle que ¿cómo sucede la sonda? Consulte a continuación (Nombre de archivo: drivers / acorn / char / pcf8583.c )
static struct i2c_driver pcf8583_driver = {
name: "PCF8583",
id: I2C_DRIVERID_PCF8583,
flags: I2C_DF_NOTIFY,
attach_adapter: pcf8583_probe, /* This will be called from i2c-core.c P.S see below function i2c_add_driver()*/
detach_client: pcf8583_detach,
command: pcf8583_command
};
Nombre del archivo: drivers / i2c / i2c-core.c
int i2c_add_driver(struct i2c_driver *driver)
{
........................
........................
/* now look for instances of driver on our adapters
*/
if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) {
for (i=0;i<I2C_ADAP_MAX;i++)
if (adapters[i]!=NULL)
/* Ignore errors */
driver->attach_adapter(adapters[i]); /*This is a location from where probe is called. Pointer **driver** is of type **pcf8583_driver** which you have passed into this function*/
}
ADAP_UNLOCK();
return 0;
}
Algunos enlaces importantes:
1) http://www.slideshare.net/varunmahajan06/i2c-subsystem-in-linux2624
2) http://www.programering.com/a/MjNwcTMwATM.html
3) http://www.linuxjournal.com/article/6717
4) http://www.developermemo.com/2943157/
5) http://free-electrons.com/doc/kernel-architecture.pdf
6) http://www.techques.com/question/1-3014627/Probe-problem-when-writing-a-I2C-device-driver
En PCI para kernel-2.4.29, se llama cuando se identifican el proveedor y la identificación del dispositivo. El controlador de bus PCI lo hace por usted. Por favor, consulte el siguiente código:
Nombre del archivo: drivers / pci / pci.c
static int pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
{
const struct pci_device_id *id;
int ret = 0;
if (drv->id_table) {
id = pci_match_device(drv->id_table, dev); /* check for device presence*/
if (!id) {
ret = 0;
goto out;
}
} else
id = NULL;
dev_probe_lock();
if (drv->probe(dev, id) >= 0) { /* This is a location from where probe is called*/
dev->driver = drv;
ret = 1;
}
dev_probe_unlock();
out:
return ret;
}