Análisis Principio uevent

resumen:

    ¿Cuál es el mecanismo principal de este trabajo es introducir uevent y proceso utilizando nodo de dispositivo de generación de mecanismo uevent a través de análisis de código. El documento se divide en dos partes, la primera parte se introduce algún conocimiento previo de los principios y uevent, mientras que la segunda parte - a través de la introducción de código para crear el dispositivo nodos mecanismo uevent.

 kernel de Linux: Linux-2.6.22.6

 La placa se desarrolló: JZ2440 V3 (S3C2440A)

declaración:

    En este artículo se está observando maestro Wei Dongshan combinado con un poco de vídeo y contenido del blog por escrito, por lo que el contenido del texto puede ser otro artículo, si usted piensa mi artículo constituye una violación de usted, usted me puede decir, seré artículos correcta, y si no puede ser el lugar adecuado en el texto, por favor, corríjanme. Gracias.

Parte 1: Principios de conocimiento y uevent antes

    Aquí comenzamos a explicar los preliminares. Antes de explicar, Echemos un vistazo en una presentación gráfica mecanismos marco uevent:

uevent

 

  Muchos de nosotros no puede saber: ¿Qué mecanismo uevent, mecanismo uevent al final lo que se ha hecho? Él es digno de aquellos aspectos de nuestra investigación?

    No hicimos uso de mecanismo de uevent cuando el conductor está aprendiendo, que no hemos utilizado en el programa class_create y class_device_create función para crear automáticamente los nodos de dispositivos en el espacio de usuario para los controladores de dispositivos. Entonces tenemos que crear manualmente nodo de dispositivo con el comando mknod en el espacio de usuario. Y cuando usamos class_create y función class_device_create, que van a crear un nodo de dispositivo en el espacio de usuario sin tener que pasar manualmente que hacer el trabajo. Y esto es lo que sabemos con mecanismo uevent macro. Y sabemos que nuestros nodos de dispositivo se crean para un controlador de dispositivo, y el controlador de dispositivo y controlador de dispositivo conectados al bus de autobús en la forma de la lista, mientras que el dispositivo - controlador - el autobús hasta el siguiente nivel es la capa sysfs . Esto conduce, por lo tanto vamos a introducir una combinación de: sysfs + mdev . Esta combinación nos dará el mecanismo para explicar la uevent principios. Empezamos a entender sysfs.

    sysfs es un sistema de archivos virtual basado en la memoria, se proporciona kernel, montar en el directorio / sys (con el fin de conseguir montar  sysfs ON / sys de los sysfs tipo (rw, el nosuid, nodev, noexec, relatime)) , responsables del árbol de dispositivos y formar un dispositivo de accionamiento que proporciona información visual al usuario del espacio de nombres . Mientras tanto SYSFS una perspectiva diferente para mostrar el sistema de acceso actual del dispositivo para nosotros:

  • / Sys / bloque de  cuestiones históricas, almacenamiento dispositivo de bloque , proporcionado con el nombre del dispositivo (tal como SDA) para un enlace simbólico / sys / dispositivos de
  • / sys / bus mediante la clasificación de tipo de bus, bajo un directorio de autobuses para encontrar enlace simbólico que conecta los dispositivos de bus, / sys / dispositivos de punto. un directorio de los conductores de autobús en el directorio contiene todo el conductor del autobús de enlace simbólico necesario para kernel correspondiente estructura de tipoDeBus
  • / Sys / clase clasificada por dispositivo de función, tal como el dispositivo de entrada bajo / sys / class / de entrada, dispositivo de gráficos en / sys / class / gráficos, el dispositivo correspondiente está apuntando a los próximos / sys / dispositivos en un grano correspondiente a un enlace simbólico la clase struct
  • / Sys / dev estratificado de controladores de dispositivos de prensa (dispositivos de caracteres / del dispositivo de bloque), siempre importante: Nombre del menor a / sys / dispositivos correspondientes a un enlace simbólico en la estructura del núcleo device_driver
  • / sys / dispositivos incluyen todos los dispositivos de registro se encuentran en una variedad de diferentes bus físico. Toda la topología física de sus dispositivos en el bus para visualizar, además de dispositivos de la plataforma y los dispositivos del sistema. colgando dispositivos de la plataforma en un chip es generalmente alta o baja bus interno y varios controladores de periféricos, la CPU puede ser dirigida directamente. dispositivos del sistema no son periférica, que es el núcleo de la estructura interna del chip, tales como CPU, temporizador, etc., por lo general no tienen el conductor relevante, pero habrá algo de código dependiente de la arquitectura para configurar el dispositivo struct kernel correspondiente en su

    Lo anterior demuestra el directorio sys bus de archivo, dispositivo, el conductor y la clase correspondiente, y su relación :

  • dispositivo que se utiliza para describir diversos aparatos que almacena toda la información del dispositivo
  • conductor para el accionamiento del dispositivo, que contiene la lista de todos los dispositivos capaces de ser conducido por él.
  • y un puente que conecta el bus de la CPU es un dispositivo que sostiene todos los dispositivos montados en él y una cadena de transmisión para el accionamiento de estos dispositivos en la lista.
  • clase se utiliza para describir una clase de dispositivo, que contiene la lista de todos los dispositivos del dispositivo.

    Aquí presentamos un bus, dispositivo, la estructura y la clase impulsado aún más bajo. sysfs funcional unificado modelo de dispositivo basado en Linux, que tiene la siguiente estructura compuesta: kobject, KSET, ktype. Podemos ver en el diagrama anterior se lleva a cabo sobre la base de la uevent kobject la estructura.

    kobject: modelo de dispositivo unificado los objetos más básicos.

struct kobject {
 	const char *name;  //name,该Kobject的名称,同时也是sysfs中的目录名称。
			    //由于Kobject添加到Kernel时,需要根据名字注册到sysfs中,之后就不能再直接修改该字段。
			   //如果需要修改Kobject的名字,需要调用kobject_rename接口,该接口会主动处理sysfs的相关事宜。
        struct list_head    entry; //entry,用于将Kobject加入到Kset中的list_head。 
        struct kobject      *parent; //parent,指向parent kobject,以此形成层次结构(在sysfs就表现为目录结构)。
        struct kset     *kset; //kset,该kobject属于的Kset。可以为NULL。
				//如果存在,且没有指定parent,则会把Kset作为parent
				//(别忘了Kset是一个特殊的Kobject)。
        struct kobj_type    *ktype;  //ktype,该Kobject属于的kobj_type。每个Kobject必须有一个ktype,或者Kernel会提示错误。
        struct sysfs_dirent *sd;   //sd,该Kobject在sysfs中的表示。
 
        struct kref     kref;  //kref,"struct kref”类型(在include/linux/kref.h中定义)的变量,为一个可用于原子操作的引用计数。
        unsigned int state_initialized:1; //state_initialized,指示该Kobject是否已经初始化,
					  //以在Kobject的Init,Put,Add等操作时进行异常校验。
        unsigned int state_in_sysfs:1;   //state_in_sysfs,指示该Kobject是否已在sysfs中呈现,以便在自动注销时从sysfs中移除。	
        unsigned int state_add_uevent_sent:1;  // state_add_uevent_sent/state_remove_uevent_sent,记录是否已经向用户空间发送ADD uevent,
						//如果有,且没有发送remove uevent,则在自动注销时,补发REMOVE uevent,
						//以便让用户空间正确处理。
        unsigned int state_remove_uevent_sent:1;
        unsigned int uevent_suppress:1;  //uevent_suppress,如果该字段为1,则表示忽略所有上报的uevent事件。
    };

 Nota: UEVENT proporciona una función de "notificación de espacio de usuario" para lograr, a través de esta función, cuando el núcleo ha aumentado kobject, borrar, modificar, y otras acciones notificará al espacio de usuario.

    Ktype: Representante kobject (estrictamente hablando, la estructura de datos que contiene los kobject) propiedades de un conjunto de operaciones (debido a la versatilidad, una pluralidad de conjunto operación kobject puede compartir la misma propiedad, y por lo tanto independiente de la ktype).

struct kobj_type {

void (*release)(struct kobject *kobj); //release,通过该回调函数,可以将包含该种类型kobject的数据结构的内存空间释放掉。

const struct sysfs_ops *sysfs_ops; //sysfs_ops,该种类型的Kobject的sysfs文件系统接口。

struct attribute **default_attrs; //default_attrs,该种类型的Kobject的atrribute列表

//(所谓attribute,就是sysfs文件系统中的一个文件)。

//将会在Kobject添加到内核时,一并注册到sysfs中。

const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);

//child_ns_type/namespace,和文件系统(sysfs)的命名空间有关

const void *(*namespace)(struct kobject *kobj);

};

    De hecho implementado aquí es similar a la kobject derivada, que contienen diferentes kobj_type de kobject puede ser visto como diferentes subclases. Esto se logra llevando a cabo las mismas funciones polimorfismo. En este diseño, que están embebidas cada kobject una estructura de datos (por ejemplo KSET, dispositivo, device_driver etc.), deben alcanzar su kobj_type, y definir donde la función de devolución de llamada.

    KSET: un kobject especial (tal y como aparecerá en el directorio "sys / /" sistema de archivos), que se utiliza para establecer kobject similar (kobject Estas propiedades puede ser el mismo, puede ser atributos diferentes).

struct kset {

struct list_head list; //list用于保存该kset下所有的kobject的链表。

spinlock_t list_lock; //list自旋锁

struct kobject kobj; //kobj,该kset自己的kobject(kset是一个特殊的kobject,也会在sysfs中以目录的形式体现)。

const struct kset_uevent_ops *uevent_ops; //uevent_ops,该kset的uevent操作函数集。

//当任何Kobject需要上报uevent时,都要调用它所从属的kset的uevent_ops,添加环境变量,

//或者过滤event(kset可以决定哪些event可以上报)。

//因此,如果一个kobject不属于任何kset时,是不允许发送uevent的。

};

    El KSET de la función de devolución de llamada operación uevent es:

struct kset_uevent_ops {

int (* const filter)(struct kset *kset, struct kobject *kobj);

//filter,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口过滤,

//阻止不希望上报的event,从而达到从整体上管理的目的。

const char *(* const name)(struct kset *kset, struct kobject *kobj);

//name,该接口可以返回kset的名称。如果一个kset没有合法的名称,

//则其下的所有Kobject将不允许上报uvent

int (* const uevent)(struct kset *kset, struct kobject *kobj,

struct kobj_uevent_env *env);

//uevent,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口统一为这些event添加环境变量。

//因为很多时候上报uevent时的环境变量都是相同的,因此可以由kset统一处理,就不需要让每个Kobject独自添加了。

};

    Tenga en cuenta que la asociación KSET y ktype , los miembros kobject usarán su propia KSET hallazgo KSET pertenece antes de su ktype es kobj.ktype. Cuando no se especifica KSET miembros, será el de construir relaciones con ktype.

     Debido a que la llamada es kobject uevent funciones de manipulación de KSET a las que pertenece, por lo KSET puede controlar su comportamiento. Si kobject no pertenecen a ninguna KSET, no se puede enviar uevent.

 

Comprender resumen, Ktype kobject y todo el mecanismo.

    función básica kobject es: mantener un recuento de referencia, cuando el recuento se reduce a cero, se libera automáticamente (en el presente documento dicho por el módulo es kobject responsable) kobject meomry espacio ocupado. Esto determina kobject debe asignarse dinámicamente (la única forma de liberación dinámica)
    Y kobject escenarios más de uso, está incrustado en una estructura de datos de gran tamaño (por ejemplo KSET, device_driver, etc.), estos estructura de datos grande, también debe ser asignado dinámicamente, la liberación dinámica. Entonces, ¿qué hora es puesto en libertad? Está incrustado liberación kobject. Pero la autorización kobject se realiza automáticamente por el módulo kobject (en el recuento de referencia es 0), entonces, ¿cómo junto con la liberación de grandes estructuras de datos que contienen ellos, entonces? 
    Entonces Ktype viene muy bien. Sabemos, Ktype la función de liberación de devolución de llamada es responsable de liberar kobject (o incluso una estructura de datos que contiene kobject de) el espacio de memoria, entonces Ktype sus funciones internas, por quién para lograrlo? Es el módulo en el que la estructura de datos de la parte superior! Sólo porque se hizo evidente kobject que está incrustado en la estructura de datos, y por kobject puntero y su propio tipo de estructura de datos, estructura de datos para encontrar el puntero a la parte superior de la necesidad de la liberación, y luego liberarlo. 
    Al hablar de esto, es mucho más clara. Por lo tanto, cada uno de las estructuras de datos kobject incrustados, por ejemplo KSET, dispositivo, device_driver etc., deben alcanzar un ktype, y definir donde la función de devolución de llamada. Del mismo modo las operaciones relativa a la sysfs, también, deben ser de tránsito ktype, porque sysfs ver kobject, pero las operaciones de archivo sujeto real, los datos se incrusta kobject estructura superior! 
    Por cierto, kobject pensamiento orientado a objetos es la máxima expresión del núcleo de Linux, pero las ventajas del lenguaje C no está aquí, así necesidad de utilizar el núcleo de Linux comparar medios inteligentes (y muy largo aliento) a realizar.

 

principio mdev

    Por encima se analizaron los sysfs, Aquí comenzamos a analizar mdev, entendemos su relación con sysfs analizando mdev. mdev se puede encontrar en el paquete de código busybox, situada busybox / util-linux / mdev.c archivo, es llamado por uevent_helper función. En mdev ver principalmente dos cosas:

Lo primero:

    Mdev -s ejecución de comandos, (mdev) de exploración / sys / block (bloque almacenado en el directorio del dispositivo / sys / block, más tarde la versión del núcleo 2.6.25, también se almacena en el dispositivo de bloque / sys / class / bloque de directorio .mdev exploración / sys / bloque para compatibilidad con versiones anteriores) atributo de archivo dev y / sys / class dos directorios, dev recuperado del archivo de propiedades para el número de dispositivo (atributo de archivo dev "mayor: menor \ n" almacenada en forma de número de dispositivo) , y un nombre de directorio que contiene el archivo DEVICE_NAME atributo dev como el nombre del dispositivo (es decir dev contiene el atributo de archivo llamado DEVICE_NAME, y que parte del directorio entre / sys / class y DEVICE_NAME denominado subsistema de directorio. es decir, cada atributo dev donde la ruta al archivo puede expresarse como / sys / class / subsistema / DEVICE_NAME / dev), crear los archivos de dispositivo adecuados en el directorio / dev . Por ejemplo, cat / sys / class / TTY / tty0 / dev serán 4: 0, subsistema es TTY, DEVICE_NAME es tty0.

La segunda cosa:

    Cuando mdev debido evento uevnet (anteriormente conocido como el evento de conexión en caliente) se llama, mdev pasando una serie de eventos uevent llegar a sus variables de entorno: ruta al dispositivo causado por la acción del evento uevent y el dispositivo se encuentra ruta del dispositivo. A continuación, determinar qué acción hizo que el evento uevent Sí. Y hacer la acción apropiada dependiendo de la operación. Si la acción es complemento, es decir, se añade un nuevo dispositivo al sistema, independientemente de si el dispositivo es un dispositivo virtual o el dispositivo físico real, mdev conseguirá a través del archivo de atributos dev en el camino de ruta del dispositivo al número de dispositivo, a continuación, ruta ruta del dispositivo al último directorio (directorio dev que contiene el atributo de archivo) que el nombre del dispositivo, crea un archivo de dispositivo correspondiente / dev directorio. Si la acción es remota, es decir, el dispositivo se retira del sistema, ruta de dispositivo / delete para el nombre de ruta último directorio bajo el directorio dev como nombre de archivo del dispositivo. Si la acción no es ni añadir ni quitar, mdev hacer nada.

    , Si queremos o eliminado del sistema en el equipo agregado al sistema, crear y borrar automáticamente los archivos de dispositivos, a continuación, debe hacer los siguientes tres puntos por el mdev Como se desprende de lo anterior:

1. En un determinado directorio subsistema / sys / class de

2. Crear un nombre de dispositivo a DEVICE_NAME como nombre,

3 y también debe contener un atributo de archivo dev DEVICE_NAME En este directorio, el dev atributo de archivo: salida del dispositivo de identificación "Mayor Menor \ n" forma.

    De lo anterior podemos conocer el contenido, sysfs para hacer el trabajo preparatorio de los mecanismos uevent que crean el directorio apropiado, y luego mdev se basa en sysfs para lograr la creación de nodos de dispositivos llamando SYSFS directorios o archivos creados.

Segunda parte: describe el uso de códigos en conjunción con el mecanismo para la creación de nodos de dispositivos uevent

    Ahora tenemos que combinar mecanismo de análisis de código uevent, mientras que tendremos que analizar este mecanismo de class_create y class_device_create estas dos funciones para analizar cómo se lleva a cabo este proceso. Ahora analizamos primero class_create:

    La siguiente es una función de la relación jerárquica class_create :

class_create(THIS_MODULE,"buttonsdrv");

    class_register(cls);

        kobject_set_name(&cls->subsys.kobj, "%s", cls->name); //将类的名字led_class赋值给对应的kset

subsys_set_kset(cls, class_subsys);

subsystem_register(&cls->subsys);

    kset_register(s); //创建class设备类目录

kset_add(k);

            kobject_add(&k->kobj);

kobject_shadow_add(kobj, NULL);

            parent = kobject_get(kobj->parent); // parent即class_kset.kobj,即/sysfs/class对应的目录

    list_add_tail(&kobj->entry,&kobj->kset->list);

    create_dir(kobj, shadow_parent); //创建一个class设备类目录

sysfs_create_dir(kobj, shadow_parent); //该接口是sysfs文件系统接口,代表创建一个目录,不再展开。

    De lo anterior se puede ver que la kobject correspondiente en sysfs es un directorio (dir), cuando registramos un kobject, llamadas kobject_add (y k-> kobj); y, posteriormente, crear el directorio de dispositivo de clase. Mientras que podemos ver la función class_create es el directorio de trabajo cuasi hecho es función class_device_create.

    La imagen desde el principio del artículo describe el kobject sabemos cuando cambia el estado (por ejemplo, añadir, eliminar, etc.), se informa al usuario de que el espacio espacio, el usuario después de recibir las notificaciones de eventos pueden ser manejados en consecuencia.
    El uevent el incidente reportado al espacio de usuario de dos maneras:
  1. Mediante el módulo kmod, llamada directamente programas ejecutables o scripts espacio de usuario.
  2. mecanismo de comunicación netlink, la entrega de eventos desde el espacio del núcleo del espacio de usuario.

    El documento explica principalmente por el módulo kmod, llamada directamente programas ejecutables o scripts espacio de usuario . Y proporciona la siguiente API (API se implementa en el archivo "lib / kobject_uevent.c") por kobject.h, módulo de uevent:

int kobject_uevent(struct kobject *kobj, enum kobject_action action);

int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,

char *envp[]);


int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);


int kobject_action_type(const char *buf, size_t count,enum kobject_action *type);

    Aquí tenemos de la función class_device_create comenzamos a analizar, para ver cómo iba la función kobject_uevent. Vemos una función de relación jerárquica class_device_create

class_device_create(buttonsdrv_class,NULL,MKDEV(auto_major,0),NULL,"buttonsdrv");

class_device_register(class_dev);

class_device_add(class_dev);

class_dev = class_device_get(class_dev);

parent_class = class_get(class_dev->class);

parent_class_dev = class_device_get(class_dev->parent);

kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);

kobject_add(&class_dev->kobj);

class_device_create_file(class_dev, attr);

class_device_add_groups(class_dev);

make_deprecated_class_device_links(class_dev);

kobject_uevent(&class_dev->kobj, KOBJ_ADD);

    Desde el código anterior y ver class_device_create class_create hacer un montón de trabajo similar - es la creación de un directorio, y cuando a las funciones kobject_uevent después de que no es lo mismo, vamos a analizar la función kobject_uevent

/**

* 通过终端事件通知用户层

*

* @action: 发生的事件 (通常是 KOBJ_ADD 和 KOBJ_REMOVE)

* @kobj: 事件发生的kobject 结构体

*

*/

int kobject_uevent(struct kobject *kobj, enum kobject_action action)

{

return kobject_uevent_env(kobj, action, NULL);

}

    Llamó la función kobject_uevent_env, mientras que la descripción anterior, sabemos que desea enviar un evento, entonces ¿cuáles son los acontecimientos de ese?

    Vemos Linux-3.5 / include / linux / kobject.h

enum kobject_action {

KOBJ_ADD, //ADD/REMOVE,Kobject(或上层数据结构)的添加/移除事件。

KOBJ_REMOVE,

KOBJ_CHANGE, //CHANGE,Kobject(或上层数据结构)的状态或者内容发生改变。

//CHANGE,如果设备驱动需要上报的事件不再上面事件的范围内,

//或者是自定义的事件,可以使用该event,并携带相应的参数。

KOBJ_MOVE, //MOVE,Kobject(或上层数据结构)更改名称或者更改Parent(意味着在sysfs中更改了目录结构)。

KOBJ_ONLINE, //ONLINE/OFFLINE,Kobject(或上层数据结构)的上线/下线事件,其实是是否使能。

KOBJ_OFFLINE,

KOBJ_MAX

};

    Veamos a continuación, analizamos la función kobject_uevent_env :

/**

* 发送一个带有环境变量的事件

*

* @action: 发生的事件(通常为KOBJ_MOVE)

* @kobj: 事件发生的kobject结构体

* @envp_ext: 环境变量数据指针

*

*/

int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,

char *envp_ext[])

{

action_string = action_to_string(action);


/* 查找当前kobject或其parent是否从属于某个kset;如果都不从属于某个kset,则返回错误。(说明一个kobject若没有加入kset,是不会上报uevent的) */

top_kobj = kobj;

while (!top_kobj->kset && top_kobj->parent) {

top_kobj = top_kobj->parent;

}

if (!top_kobj->kset) {

pr_debug("kobject attempted to send uevent without kset!\n");

return -EINVAL;

}


kset = top_kobj->kset;

uevent_ops = kset->uevent_ops;


/* 如果所属的kset有uevent_ops->filter,则调用该函数,若该函数返回0,则过滤此次上报。(kset 可以通过filter接口过滤不希望上报的event) */

if (uevent_ops && uevent_ops->filter)

if (!uevent_ops->filter(kset, kobj)) {

pr_debug("kobject filter function caused the event to drop!\n");

return 0;

}


/*判断所属的kset是否有合法的名称,若uevent_ops->name存在就用其返回的名称作为subsystem;若uevent_ops->name不存在就用kset本身的kobject的名称作为subsystem;若没有合法的名称,则不上报uevent */

if (uevent_ops && uevent_ops->name)

subsystem = uevent_ops->name(kset, kobj);

else

subsystem = kobject_name(&kset->kobj);

if (!subsystem) {

pr_debug("unset subsytem caused the event to drop!\n");

return 0;

}


/* 分配一个此次上报的环境变量 */

envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);

if (!envp)

return -ENOMEM;


/*分配一个此次上报的用于保存环境变量的buffer, */

buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);

if (!buffer) {

retval = -ENOMEM;

goto exit;

}


/* 获得该kobject在sysfs中路径 */

devpath = kobject_get_path(kobj, GFP_KERNEL);

if (!devpath) {

retval = -ENOENT;

goto exit;

}


/* uevent_helper的环境变量*/

envp[i++] = "HOME=/";

envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";


/* 添加环境变量 */

scratch = buffer;

envp [i++] = scratch;

scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;

envp [i++] = scratch;

scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;

envp [i++] = scratch;

scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;

for (j = 0; envp_ext && envp_ext[j]; j++)

envp[i++] = envp_ext[j];

/* just reserve the space, overwrite it after kset call has returned */

envp[i++] = seq_buff = scratch;

scratch += strlen("SEQNUM=18446744073709551616") + 1;


/* 如果 uevent_ops->uevent 存在,调用该接口,添加kset统一的环境变量到env指针 */

if (uevent_ops && uevent_ops->uevent) {

retval = uevent_ops->uevent(kset, kobj,

&envp[i], NUM_ENVP - i, scratch,

BUFFER_SIZE - (scratch - buffer));

if (retval) {

pr_debug ("%s - uevent() returned %d\n",

__FUNCTION__, retval);

goto exit;

}

}


/* 调用add_uevent_var接口,添加格式为"SEQNUM=%llu”的序列号 */

spin_lock(&sequence_lock);

seq = ++uevent_seqnum;

spin_unlock(&sequence_lock);

sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);



/* 以uevent_helper、 subsystem 以及添加了标准环境变量(HOME=/,PATH=/sbin:/bin:/usr/sbin:/usr/bin)的env指针为参数,调用kmod模块提供的call_usermodehelper函数,上报uevent。 */

if (uevent_helper[0]) {

char *argv [3];


argv [0] = uevent_helper;

argv [1] = (char *)subsystem;

argv [2] = NULL;

call_usermodehelper (argv[0], argv, envp, 0);

}

}

    uevent módulo kmod reportado por uevent, pasará call_usermodehelper función, llamar al archivo ejecutable en el espacio de usuario (o secuencia de comandos, por ayudante uevent corta) controlar el evento. ¿Qué uevent ayudante uevent_helper ruta almacenada en la matriz. Puede compilar los elementos de configuración del kernel por CONFIG_UEVENT_HELPER_PATH, estáticamente asignar ayudante uevent.
    Pero de esta manera será para cada evento tenedor de un proceso, como el número de dispositivos soportados por el núcleo, el inicio del sistema de esta manera sería fatal (puede llevar a desbordamiento de memoria, etc.). Por lo tanto, sólo la versión anterior del kernel se utiliza de esta manera, y ahora no se recomienda el kernel para utilizar de esta manera. Por lo tanto, al compilar el núcleo, es necesario configurar el punto en blanco. Tras el inicio del sistema, la mayor parte del equipo se ha preparado, según sea necesario, para volver a asignar un ayudante uevent, por lo que el proceso de sistema de detección de marcha en eventos de conexión en caliente.
    Esto se puede conseguir escribiendo a la ruta ayudante archivo "/ sys / kernel / uevent_helper". De hecho, la forma de sistema de archivos sysfs el núcleo, que el usuario abra la matriz uevent_helper espacio para el acceso a modificar el espacio de usuario específico programa de referencia "./kernel/ksysfs.c" código correspondiente.

    Añadir echo "/ sbin / mdev" en escritura /etc/init.d/rcS> / proc / sys / kernel / hotplug, se encuentra el cat / sys / kernel / uevent_helper es decir / sbin / mdev. Ruta ejecutable Descripción / proc / sys / kernel / hotplug es finalmente incluido en / sys / kernel / uevent_helper en. A repetir manualmente "/ kernel / main"> uevent_helper ( antes / sbin / mdev será sobrescrito), cuando lsmod, cuando rmmod, / sys / kernel / uevent_helper en / kernel / principal se ejecutará, lo que indica que un evento ha informado al usuario espacio.

Aquí nos fijamos en el Busybox es cómo crear un nodo de dispositivo.

    Gire mdev jugado, la descripción anterior es la creación de un directorio o un archivo en el sistema de archivos sysfs y aplicaciones del dispositivo para acceder a las necesidades de archivo que se creará en el directorio / dev /. El trabajo realizado por el mdev.
    mdev principio es explicar las reglas de nomenclatura de archivos de dispositivos /etc/mdev.conf archivo de definición, y crea archivos de dispositivos de conformidad con los requisitos establecidos en las normas de las variables de entorno. mdev.conf especificada por la capa de usuario, y por lo tanto más flexible. Este artículo no está destinado para ampliar el análisis de la secuencia de comandos de configuración MDEV. El conocimiento puede ver mi traducción: traducción mdev.conf

    MDEV programa apropiado en Busybox / util-linux / mdev.c

int mdev_main(int argc UNUSED_PARAM, char **argv)

    xchdir("/dev");

    if (argv[1] && strcmp(argv[1], "-s")//系统启动时mdev –s才会执行这个分支

    else

    action = getenv("ACTION");

    env_path = getenv("DEVPATH");

    G.subsystem = getenv("SUBSYSTEM");

    snprintf(temp, PATH_MAX, "/sys%s", env_path);//到/sysfs/devices/led目录

    make_device(temp, /*delete:*/ 0);

    strcpy(dev_maj_min, "/dev"); //读出dev属性文件,得到设备号

    open_read_close(path, dev_maj_min + 1, 64);    

    ….

    mknod(node_name, rule->mode | type, makedev(major, minor)) //最终mknod创建节点

    Con el tiempo vamos a realizar un seguimiento de mknod para crear dispositivos en / dev /.

referencias:

Linux unificado sysfs de referencia, las udev, y detrás de ellos
el modelo de dispositivo Linux (2) _Kobject
crear archivos del dispositivo y mdev Linux
uevent kernel uevent envía la API, los usuarios espacialmente resueltas
modelo de dispositivo Linux (3) _Uevent
uevent mecanismo del modelo de dispositivo

Publicados 407 artículos originales · ganado elogios 150 · vistas 380 000 +

Supongo que te gusta

Origin blog.csdn.net/ds1130071727/article/details/102854649
Recomendado
Clasificación