En linux a través del sistema de archivos proc para el estado del usuario y la interacción del estado del kernel o el ajuste fino del kernel es un medio relativamente simple y efectivo. Recientemente, debido a las necesidades del proyecto, debe enviar los datos de un módulo del kernel al modo de usuario a través de proc, y aprovechar la oportunidad de aprender seq_file. Haga un registro simple aquí, y el lugar equivocado es bienvenido para criticar y corregir. Para usar seq_file, necesita #include
Ok, no más tonterías, comencemos, ^ _ ^. Supongamos que, en uno de nuestros módulos del kernel, hay un conjunto de datos almacenados en estructuras de datos iterables (como listas vinculadas, arreglos, etc.), quiero enviarlos al estado del usuario a través de proc y verlos a través de cat, etc. Como hacerlo En aras de la simplicidad, supongamos que tenemos una lista de datos vinculados, el encabezado de la lista enlazada es apuntado por una variable llamada list_head, que a su vez está protegida con un bloqueo de lectura y escritura. La estructura de un nodo de lista enlazada es la siguiente:
struct node {
struct node * next;
int num;
};
Struct node * list_head; //encabezado de la tabla de la cadena
DEFINE_RWLOCK (list_lock); //Definir e inicializar un bloqueo de giro de lectura-escritura.
seq_file define un conjunto de punteros de función para la iteración, que funciona como un iterador hacia adelante en C ++, pero con un miembro llamado show para generar información del nodo. Este conjunto de punteros de función se declara en una estructura llamada struct seq_operations de la siguiente manera:
struct seq_operations {
void * (* start) (struct seq_file * m, loff_t * pos);
void (* stop) (struct seq_file * m, void * v);
void * (* next) (struct seq_file * m, void * v, loff_t * pos); Br>
int (* show) (struct seq_file * m, void * v);
};
start puede hacer un trabajo de adquisición e inicialización de recursos, bastante c ++ constructor El rol, su valor de retorno se pasará a ellos como el segundo parámetro de la primera presentación de llamada y la siguiente, luego cada vez que llamará a la siguiente, y mostrará; comience si se devuelve NULL, entonces la parada de llamada directamente no llamará a la función de mostrar y Siguiente Si hay algunos encabezados para generar, puede regresar al kernel SEQ_START_TOKEN. Se define como:
#define SEQ_START_TOKEN ((void *) 1)
El valor de retorno de next se usará como el programa y la próxima llamada. El segundo argumento de next (es decir, v) se pasa a ellos, y cuando el siguiente devuelve NULL, se llama a stop.
La función de detención es similar a la función de los destructores en las clases de c ++, responsable de la limpieza de recursos y las operaciones de devolución.
La función show devuelve 0 correctamente, y el error devuelve el código de error correspondiente.
Tenga en cuenta que la información de salida es mayor que el búfer asignado por el kernel a la vez (como el motivo específico, la próxima vez que escriba sobre la implementación de seq_read y otras funciones, estará claro en ese momento) comience, muestre, a continuación , la parada se puede llamar varias veces, lo que requiere el tercer parámetro pos de start y next para distinguirlos. Por lo tanto, su orden de invocación se puede describir de la siguiente manera: inicio- > show- > next- > show- > next- > show- > ...- > next- > stop.
Tenga en cuenta que también puede ser el siguiente (iniciar la llamada de parada varias veces): start- > show- > next- > show- > next- > show- > ...- > next- > stop- > start- > show- > next ...- > next- > stop. Estas funciones iterativas se pueden definir en nuestro ejemplo de la siguiente manera:
static void * my_start (struct seq_file * m, l loff_t * pos)
{
int i = 1;
struct node * tmp_entry;
read_lock_bh (list_lock); //Obtiene un bloqueo de giro de lectura-escritura
if (* pos == 0) {
devolver SEQ_START_TOKEN;
}
para (tmp_entry = list_head; tmp_entry! = NULL; tmp_entry = tmp-entry- > next) {
if (i == * pos)
return tmp_entry;
++ i;
}
return NULL;
}
static void my_stop (struct seq_file * m, void * v)
{
read_unlock_bh (tmp_lock); //libere el bloqueo de giro
seq_printf (m, " \\ n \\ n ------------- fin de información de datos --------------------------- ");
}
void estático * my_next (struct seq_file * m, void * v, loff_t * pos)
{
++ * Pos;
return (SEQ_START_TOKEN == v)? List_head: ((struct node *) v) - &g t; next;
}
static int my_show (struct seq_file * m, void * v)
{
struct node * tmp_entry;
static int line_count = 0;
if (SEQ_START_TOKEN == v) {
seq_printf (m, " \\ n \\ n ---------- --- la información de los datos comienza --------------------------- \\ n \\ n ");
} else else < Br>
tmp_entry = (struct node *) v;
seq_file (m, "% d, quot; tmp_entry- > num);
if (++ line_count = = 10) {//Una línea genera diez datos
seq_printf (m, " \\ n ");
line_count = 0;
}
}
return 0;
}
Luego, defina una estructura seq_operations de la siguiente manera:
static const struct seq_operations my_seq_ops = {
.start = my_start,
.next = my_next,
.stop = my_stop,
.show = my_show,
};
En este punto, también debemos definir una función para enviar la dirección de my_seq_ops al kernel. De la siguiente manera,
static int proc_my_test_open ((struct inode * inode, struct file * file)
{
return seq_open (file, &my_seq_ops);
}
Finalmente, defina una estructura struct file_operations, nuestro proc_my_test_open se pasa al kernel, y se llama a proc_create, creando un directorio proc y listo. El código es el siguiente:
static const struct file_operations my_file_ops = {
.owner = THIS_MODULE,
.open = proc_my_test_open,
.read = seq_read, < Br>
.llseek = seq_lseek,
.release = seq_release,
};
my_file_opsproc_create (" my_test ", 0, NULL, &my_file_ops);
De hecho, para resultados simples, simplemente puedes definir una función de show y luego a través de single_open en lugar de nuestro seq_open aquí, este método es relativamente simple, el método específico puede ser google.
Explique la salida del comando free en Linux. El siguiente es el resultado de la ejecución l
El entorno de instalación es Ubuntu 13.10 versión i386. El servidor nginx y el servidor mys
Ubuntu portátil a una red LAN, conecte el cable de internet, luz indicadora de cable de red, pero in
en la parte posterior de un contenedor recientemente jugó ventana acoplable en la máquina virtual b
Los usuarios comunes de Linux camuflan a los usuarios de root
sistema Linux remoto VNC está conectado software VNC establece
Cómo utilizar Linux para conectarse de forma anónima: Cuatro armas mágicas
Varios comandos de Linux para comprender el rendimiento de los sistemas Linux
Configuraciones de firewall de Linux
Comandos de configuración de red bajo Linux
Sistema Win7 cómo exportar la URL de la colección para evitar el fenómeno de pérdida
Win10 Mobile Preview 10512 Beyond 10240 es una nueva rama de TH2
Cómo ver la contraseña de WiFi cuando está conectado WiFi
Win7 crear imagen de copia de seguridad es más flexible que Ghost
¿Cómo activar la versión oficial de Win10 gratis? La versión oficial de
Cómo evitar que el troyano ASP se ejecute en el servidor
Iniciar el proceso de entrar en el brazo del núcleo de Linux
El sistema Win7 vuelve al escritorio, hay una solución al problema de la instalación transparente.
Sistema Win7 para mejorar la velocidad de apertura de la página web