Red de conocimiento informático - Material del sitio web - Cómo crear manualmente nodos de dispositivos y escribir comandos y parámetros principales

Cómo crear manualmente nodos de dispositivos y escribir comandos y parámetros principales

Hay tres formas de generar archivos de nodo de dispositivo de controlador en Linux: 1. mknod manual 2. Use devfs 3. Use udev

Cuando comience a escribir un controlador de dispositivo Linux, muchas veces los nodos de dispositivo serán; creado manualmente usando el comando mknod. De hecho, el kernel de Linux nos proporciona un conjunto de funciones que se pueden usar para crear automáticamente el nodo de dispositivo correspondiente en el directorio /dev cuando se carga un módulo y eliminar el nodo cuando se descarga el módulo.

Antes de 2.6.17, era fácil generar archivos de dispositivo en el directorio /dev

devfs_mk_bdev

devfs_mk_cdev

devfs_mk_symlink

devfs_mk_dir

devfs_ remove

Estas son API de devfs puras, disponibles antes de 2.6.17.

class_device_create_file tampoco funciona después de la versión 2.6.26. Device_create se utiliza actualmente, disponible desde 2.6.18

struct device *device_create(struct class *class, struct device *parent,

dev_t devt, const char *fmt, . .. )

Desde 2.6.26, hay un parámetro adicional drvdata: los datos que se agregarán al dispositivo para las devoluciones de llamada

Si no sabes cómo usarlo, puedes La asignación de parámetros es NULL

struct device *device_create(struct class *class, struct device *parent,

dev_t devt, void *drvdata, const char *fmt, ...)

El tercer método, udev, se resaltará a continuación

Para agregar soporte udev a un controlador, lo principal que debe hacer es llamar a class_create en el código de inicialización del controlador (... ). Cree una clase para los dispositivos y llame a device_create(...) para cada dispositivo. En kernels 2.6 anteriores, llamar a class_device_create(...) crea el dispositivo correspondiente.

La estructura de clase struct se define en el kernel. Como sugiere el nombre, una variable de tipo de estructura de clase struct corresponde a una clase. El kernel también proporciona la función class_create(...), que se puede utilizar. para crear una clase. La clase se almacena en En sysfs, una vez que se crea la clase, se llama a la función device_create(...). Una vez creada la clase, llame a la función device_create(...) para crear el nodo de dispositivo correspondiente en el directorio /dev. De esta manera, cuando se carga el módulo, udev en el espacio de usuario responderá automáticamente a la función device_create(...) y buscará la clase correspondiente en /sysfs para crear el nodo del dispositivo.

struct class y class_create(...) y device_create(...) están incluidos en /include/linux/device.h.

structruct.h

La clase struct se define en el archivo de encabezado include/linux/device.h

class_create(...) en /drivers/ base/ Implementado en class.c

device_create(....) está implementado en /drivers/base/class.c

device_create(...) todos están incluidos en / include/linux /device.h; de lo contrario, el compilador generará un error. ...) la función se implementa en /drivers/base/core.c

class_destroy(...), device_destroy(...) también se implementa en /drivers/base/core.c.

El proceso de llamada es similar al siguiente:

clase de estructura estática *spidev_class;

/*------------------- -------------------------------- -------------------- -------- --*/

static int __devinit spidev_probe(struct spi_device *spi)

{

....

dev =device_create (spidev_class, & spi-gt; dev, spidev-gt; devt,

spidev, "spidevd.d",

spi-gt ; master-gt; bus_num, spi-gt;chip_select);

...

}

static int __devexit spidev_remove(struct spi_device *spi)

{

......

dispositivo_destroy(spidev_class, spidev-gt; devt

.....

devuelve 0;

}

estructura estática spi_driver spidev_spi = {

.driver = {

. nombre = "spidev",

.owner = ESTE_MODULE,

},

.probe = spidev_probe,

.remove = __devexit_p (spidev_remove),

};

/*---------------------- ------ ------------------------------------------- --*/

static int __init spidev_init(void)

{

....

spidev_class =class_create(ESTE_MODULE, "spidev");

if ( IS_ERR(spidev_class)) {

unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);

return PTR_ERR(spidev_class)

}

....

}

module_init(spidev_init);

static void __exit spidev_exit(void)

{

......

class_destroy(spidev_class);

......

}

module_exit(spidev_exit);

MODULE_DESCRIPTION("Interfaz de dispositivo SPI en modo usuario

e");

MODULE_LICENSE("GPL");

MODULE_LICENSE("GPL");

A continuación se muestra un controlador de dispositivo de caracteres simple que muestra cómo utilizar estas funciones

#include lt;linux/module.hgt;

#include lt;linux/kernel.hgt;

#include lt;linux/init.hgt ;

#include lt;linux/cdev.hgt;

#include lt;linux/device.hgt;

int HELLO_MAJOR = 0;

Incluir lt;linux/kernel.hgt;

#include lt;linux/init.devno;

struct hello_dev {

struct dispositivo * dev ;

dev_t chrdev;

struct cdev cdev;

};

estructura estática hello_ dev *my_hello_dev = NULL;

p>

estructura file_operaciones hello_fops = {

.owner = ESTE_MODULE

};

static int __init hello_init (void)

{

int err = 0;

struct dispositivo *dev;

my_hello_dev = kzalloc(sizeof(struct hello_dev), GFP_KERNEL);

if ( NULL == my_hello_dev) {

printk("s kzalloc falló!\n", __func__);

return -ENOMEM;

}

devno = MKDEV(HOLA_MAJOR, HOLA _MINOR);

if (HOLA_MAJOR)

err= registrar_chrdev_region(my_hello_dev-gt; chrdev, 2, "memdev ");

else

{

err = alloc_chrdev_region(amp;my_hello_dev-gt;chrdev, 0, 2, "memdev") ;

HOLA_MAJOR = MAYOR(devno);

}.

if (err) {

printk("s alloc_chrdev_region falló!\n", __func__

goto alloc_chrdev_err

}

printk("MAJOR IS d\n",HELLO_MAJOR);

cdev_init(amp; (my_hello_dev-gt;cdev), amp;hello_fops);

my_hello_dev-gt;cdev.owner = ESTE_MODULE;

err=cdev_add(amp;(my_hello_dev-gt;cdev),amp;hello_fops);

cdev = cdev_add(amp ;(my_hello_dev-gt;cdev), my_hello_dev-gt;chrdev, 1);

if (err) {

printk("s cdev_add falló!\n", __func__) ;

ir a cdev_add_err;

}

printk(KERN_INFO "Controlador de caracteres registrado/n");

my_class =class_create(THIS_MODULE , "hello_char_ class"); //nombre de clase hello_char_class

if(IS_ERR(mi_clase))

{

err = PTR_ERR(mi_clase); p>

printk("s class_create falló!\n", __func__functor("class_create falló! n", __func__);

goto class_err;

}

dev=device_create(my_class, NULL, my_hello_dev-gt; chrdev, NULL, "memdevd", 0); //El dispositivo llamado memdev

if (IS_ERR(dev)){< / p>

err = PTR_ERR(dev);

gyro_err(¡el dispositivo_create falló! \n",__func__);

goto device_err;

}

printk("hola inicialización del módulo\n");

return 0;

device_err:

device_destroy(my_class, my_hello_dev- gt; chrdev);

class_err:

cdev_del(my_hello_dev- gt;chrdev);

cdev_add_err:

unregister_chrdev_region(my_hello_ dev-gt;chrdev, 1);

alloc_chrdev_err:

kfree (my_hello_dev);

p>

return err;

}

static void __exit hello_exit (void)

{

cdev_del (amp; ( my_hello_dev-gt;cdev));

unregister_chrdev_region (my_hello_dev-gt;chrdev, 1);

device_destroy(my_class, devno); //eliminar el nodo del dispositivo en /dev// Primero debe eliminar el dispositivo, luego la clase class

class_destroy(my_class); //eliminar la clase creada por nosotros

printk (KERN_INFO "char driver cleanup\n");

}

módulo_init (hola_init);

módulo_exit (hola_salida)

MÓDULO_LICENCIA ("GPL");

De esta manera, después de cargar el módulo, el nodo del dispositivo memdev se puede encontrar en el directorio /dev.

Ejemplo 2: Controladores/i2c/i2c-dev en el kernel.

Llame a device_create(i2c_dev_class,&adap-gt;dev,

MKDEV( I2C_MAJOR, adap-gt;nr), NULL,

"i2c-d", adap-gt;nr);

Esto generará un i2c-0 en el directorio dev O i2c- 1 nodo

El siguiente paso es la aplicación udev. udev es algo en la capa de aplicación. udev necesita el soporte de kernel sysfs y tmpfs proporciona entrada de dispositivo y canal uevent para udev, y tmpfs es udev. Proporcione espacio de almacenamiento para el archivo del dispositivo

El código fuente de udev se puede descargar de los sitios web relevantes y luego trasplantar su entorno de ejecución, especificar el entorno de compilación cruzada y modificar CROSS_COMPILE en Makefile Make CROSS_COMPILE=mipsel-linux-, DESTDIR. =xxx o haga CROSS_COMPILE =mipsel-linux-, DESTDIR=xxx e instale y copie udevd y udevstart en el directorio /sbin/ de rootfs, y copie los archivos de configuración de udev udevd y udevstart en el directorio /sbin/.

Copie los archivos de reglas en los archivos de configuración de udev udev.conf y reglas.d al directorio /etc/ en rootfs

Luego en rootfs/etc/init.d/rcS agregue el siguientes líneas para:

echo "Iniciando udevd ..."

udevd y udevstart en el directorio /sbin/.

/sbin/udevd --daemon

/sbin/udevstart

(El contenido del rcS original es el siguiente:

# montar sistemas de archivos

/bin/mount -t proc /proc /proc

/bin/mount -t sysfs sysfs /sys

/bin/mount - t tmpfs tmpfs / dev

# crear dispositivos necesarios

/bin/mknod /dev/null c 1 3

/bin/ mkdir /dev/pts

/bin/mount -t devpts devpts /dev

/bin/mount -t devpts devpts /dev

/bin/mount -t devpts devpts /dev

/bin/mount -t devpts devpts /dev

/bin/mountt devpts devpts /dev/pts

/bin/mknod /dev/audio c 14 4

/bin/mknod /dev/ts c 10 16

)

De esta manera, cuando se inicia el sistema, udevd y udevstart analizarán el archivo de configuración y cree automáticamente el archivo de nodo del dispositivo a continuación.