Red de conocimiento del abogados - Ley de patentes - ¿De qué partes consta una macro?

¿De qué partes consta una macro?

1. Escriba las funciones de apertura y escritura

2. Dígaselo al kernel

1) Defina una estructura struct file_operations y rellénela

static struct file_operations first_drv_fops = {

.owner = THIS_MODULE, /* Esta es una macro que empuja la variable __this_module creada automáticamente al compilar el módulo*/

.open = first_drv_open ,

.write = first_drv_write,

};

2), le dice al kernel la estructura struct file_operations

major = Register_chrdev( 0, "first_drv", amp; first_drv_fops); //Registrar, informar al kernel

Parámetros relacionados: primero, número de dispositivo, 0 asigna automáticamente el número de dispositivo principal, de lo contrario, el número de dispositivo principal 0-255

Segundo: nombre del dispositivo

Segundo: estructura struct file_operatives

4) Quién llama a Register_chrdev (llamada a función de entrada)

static int first_drv_init( void)

5), la función de entrada debe modificarse con una macro del núcleo

module_init(first_drv_init);

module_init definirá una estructura. El puntero de función en esta estructura apunta a la función first_drv_init. Cuando cargamos o instalamos un controlador, el kernel encontrará automáticamente esta estructura y luego llamará al puntero de función interna. Este puntero de función apunta a la función first_drv_init. el kernel la estructura struct file_operaciones

6). Si hay una función de entrada, habrá una función de salida

module_exit(first_drv_exit);

Finalmente agregue el protocolo

MODULE_LICENSE("GPL");

3. mdev crea automáticamente nodos de dispositivo basados ​​en la información del sistema:

Es demasiado problemático crear un dispositivo manualmente. archivos cada vez que escribe un controlador, es mucho más conveniente utilizar el sistema de archivos de administración del dispositivo. Devfs se ha utilizado antes del kernel 2.6, pero tiene muchos defectos. Crea una gran cantidad de archivos de dispositivo que en realidad no existen. Además, la asignación entre dispositivos y archivos de dispositivos es incierta. Por ejemplo, un disco U puede corresponder a sda o sdb. No hay suficientes números de dispositivos primarios/secundarios. El kernel posterior a 2.6 introdujo el sistema de archivos sysfs, que se monta en /sys. Cuando se usa con udev, puede completar las funciones de devfs y compensar esas deficiencias. (Permítanme mencionar aquí que el kernel actual ya usa netlink).

udev es una aplicación en el espacio del usuario. En las aplicaciones integradas, se usa mdev y mdev está en ocupado. mdev es una versión simplificada de udev.

Primero agregue la opción para admitir mdev en Busybox:

Utilidades del sistema Linux ---gt

[*] mdev

[*] Soporte /etc/mdev.conf

[*] Soporte de subdirectorios/enlaces simbólicos

[*] Soporte de sustituciones de expresiones regulares al cambiar el nombre del dispositivo

[* ] Admite la ejecución de comandos al agregar o eliminar dispositivos

Luego modifique /etc/init.d/rcS:

echo /sbin/mdev gt /proc/sys/kernel/hotplug

/sbin/mdev -s

Ejecute mdev -s: use '-s' como parámetro para llamar a mdev escrito en el directorio /sbin (en realidad es un enlace, la función es pasar parámetros al programa /busybox en el directorio bin y llamarlo), mdev escanea todos los directorios de dispositivos de clase en /sys/class y /sys/block si hay un archivo llamado dev en el directorio y el archivo contiene el número de dispositivo. , mdev utilizará esta información para crear un archivo de nodo de dispositivo en /dev para este dispositivo. Generalmente, mdev -s se ejecuta solo una vez al inicio.

Evento de conexión en caliente: Dado que el comando: echo /sbin/mdev gt; /proc/sys/kernel/hotplug se ejecuta al inicio, cuando se produce un evento de conexión en caliente, el kernel llamará al mdev del Directorio /sbin. En este momento, mdev usa ACTION y DEVPATH en las variables de entorno para determinar la acción del evento de conexión en caliente y qué directorio en /sys se ve afectado.

Luego verificará si hay un archivo de atributos dev en este directorio. Si lo hay, use esta información para crear un archivo de nodo de dispositivo para este dispositivo en /dev

Vuelva a empaquetar el sistema de archivos, de modo que /. directorio sys, / Hay algo en el directorio dev

El siguiente es el prototipo de create_class:

#define class_create(propietario, nombre) /

( { /

static struct lock_class_key __key; /

__class_create(propietario, nombre, amp; __key); extern struct class * __must_check __class_create( struct module *owner,

const char *name,

struct lock_class_key *key

El prototipo de class_destroy es como siguiente:

extern void class_destroy(struct class *cls);

El prototipo de device_create es el siguiente:

extern struct device *device_create(struct class * cls, struct dispositivo *parent,

dev_t devt, void *drvdata,

const char *fmt, ...)

__attribute__((format(printf , 5, 6)));

El prototipo de device_destroy es el siguiente:

extern void device_destroy(struct class *cls, dev_t devt

); El uso específico es el siguiente, consulte los siguientes ejemplos:

static struct class *firstdrv_class;

static struct class_device *firstdrv_class_dev;

firstdrv_class = class_create (ESTE_MODULE, "firstdrv");

firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(principal, 0), NULL, "xyz"); p>class_device_unregister(firstdrv_class_dev);

class_destroy(firstdrv_class);

Echemos un vistazo a cómo la aplicación encuentra esta estructura

En la aplicación que usamos

Utilice open para abrir un dispositivo: como por ejemplo: open(/dev/xxx, O_RDWR);

xxx tiene un atributo, como el carácter del dispositivo es c, seguido de permisos de lectura y escritura, así como el nombre del dispositivo principal y el nombre del dispositivo secundario, cuando registramos, registramos la estructura first_drv_fops en la matriz del kernel chrdev a través de Register_chrdev(0, "first_drv", amp; first_drv_fops) (con el número de dispositivo principal, el nombre del dispositivo, la estructura struct file_operations), y hay una función de escritura abierta en la estructura, entonces, ¿cómo la encuentra la aplicación? De hecho, encuentra los first_drv_fops que registramos en la matriz del núcleo chrdev según el tipo de dispositivo y el número de dispositivo principal en los atributos del archivo abierto.

Código de ejemplo:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

clase de estructura estática *firstdrv_class;

estructura estática class_device *firstdrv_class_dev;

volatile unsigned long *gpfcon = NULL;

volatile unsigned long *gpfdat = NULL;

static int first_drv_open(struct inode *inode, struct file *file)

{

//printk("first_drv_open\n ");

/* Configurar GPF4, 5 y 6 como salida */

*gpfcon amp;= ~((0x3lt;lt;(4*2)) | ( 0x3lt;lt;(5*2)) | (0x3lt; lt; (6*2)));

*gpfcon |= ((0x1lt; lt; (4*2)) | (0x1lt ; lt; (5*2)) | (0x1lt;lt;(6*2)));

devuelve 0;

}

estático ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

{

int val;

//printk(" first_drv_write\n");

copy_from_user(amp; val, buf, count); // copy_to_user();

if (val == 1)

{

// Ilumina

*gpfdat amp;= ~((1lt;lt;4) | (1lt;lt;5) | (1lt;lt;6) );

}

else

{

// Apaga la luz

*gpfdat |= (1lt; lt; 4) |

t;lt;5) | (1lt;lt;6);

}

devuelve 0;

}

estructura estática file_operations first_drv_fops = {

.owner = THIS_MODULE, /* Esta es una macro que empuja la variable __this_module creada automáticamente al compilar el módulo*/

.open = first_drv_open,

.write = first_drv_write,

};

int mayor;

static int first_drv_init(void)

{

major = Register_chrdev(0, "first_drv", & first_drv_fops); // Registrarse, informar al kernel

firstdrv_class = class_create(THIS_MODULE, "firstdrv");

firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(principal, 0), NULL, "xyz"); /* /dev/xyz */

gpfcon = (volatile unsigned long *)ioremap( 0x56000050 , 16);

gpfdat = gpfcon 1;

devuelve 0;

}

vacío estático first_drv_exit(void)

{

unregister_chrdev(major, "first_drv"); // Desinstalar

class_device_unregister(firstdrv_class_dev);

class_destroy(firstdrv_class);

p>

iounmap(gpfcon);

}

module_init(first_drv_init);

module_exit(first_drv_exit);

MODULE_LICENSE ("GPL");

Makefile para compilación

KERN_DIR = /work/system/linux-2.6.22.6

todos:

make -C $(KERN_DIR) M=`módulos `pwd`

limpiar:

make -C $(KERN_DIR) M=`módulos `pwd` limpio

rm -rf module.order

obj-m = first_drv.o

Programa de prueba:

#include

# include

#include

#include

/* firstdrvtest activado

* firstdrvtest desactivado

*/

int main(int argc, char **argv)

{

int fd;

int val = 1;

fd = open("/dev/xyz", O_RDWR

if (fd lt; 0)

{

printf("¡no se puede abrir!\n");

}

if (argc != 2)

{

printf("Uso:\n");

printf("s \n", argv[0]);

devuelve 0;

p>

}

if (strcmp(argv[1], "on") == 0)

{

val = 1;

}

más

{

val = 0

}

escribir (fd, amp; val, 4

devolver

}

;