GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo crear archivos Proc de Linux en el programa C usando LKM

El sistema de archivos proc refleja el estado actual del kernel de Linux.

El estado actual del kernel podría representar información diversa, como los procesos que se ejecutan en él, la información del hardware, la información de la red, etc. Por lo tanto, este sistema está diseñado de manera que los procesos a nivel de usuario puedan acceder fácilmente a toda esta información.

También decimos que un sistema de archivos proc es un pseudo sistema de archivos. Esto se debe a que los archivos en este sistema de archivos se cargan con información cuando se accede a estos archivos y esa es la razón por la cual los archivos en este sistema de archivos generalmente muestran un tamaño cero.

Haga un ls /proc en su sistema y notará algo similar a lo siguiente:

$ ls /proc
1  15  1681  1719 35 60  713  878 cgroups filesystems kpageflags pagetypeinfo sysrq-trigger ....

Entonces vemos que este sistema de archivos contiene archivos y directorios. Los nombres de archivos o directorios son alfabéticos o numéricos. Los nombres numéricos de archivos o directorios corresponden principalmente a los procesos que se ejecutan en el sistema y el número representa el ID de proceso del proceso. Por lo tanto, es muy fácil conocer la información a nivel de kernel sobre cualquier proceso utilizando su ID de proceso y abriendo el archivo correspondiente.

En este artículo, nos basaremos en nuestro conocimiento de los módulos del kernel cargables (LKM) y discutiremos cómo se crean, leen y escriben estos archivos proc.

Consulte nuestro artículo anterior sobre el sistema de archivos proc de Linux para comprender los diversos archivos que se encuentran en /proc.

Creación de archivos de proceso

En el artículo sobre los módulos del kernel de Linux, discutimos cómo crear, cargar y descargar LKM. Ese fue el concepto básico para agregar más funcionalidad al kernel de Linux en tiempo de ejecución. Los archivos proc funcionan según el mismo principio. Cada archivo de proceso se crea, carga y descarga en forma de LKM.

En el siguiente código, intentamos crear un archivo proc y definir sus capacidades de lectura y escritura.

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>

#define MAX_LEN       4096
int read_info( char *page, char **start, off_t off,int count, int *eof, void *data );
ssize_t write_info( struct file *filp, const char __user *buff,unsigned long len, void *data );

static struct proc_dir_entry *proc_entry;
static char *info;
static int write_index;
static int read_index;

int init_module( void )
{
    int ret = 0;
    info = (char *)vmalloc( MAX_LEN );
    memset( info, 0, MAX_LEN );
    proc_entry = create_proc_entry( "procEntry123", 0644, NULL );

    if (proc_entry == NULL)
    {
        ret = -1;
        vfree(info);
        printk(KERN_INFO "procEntry123 could not be created\n");
    }
    else
    {
        write_index = 0;
        read_index = 0;
        proc_entry->read_proc = read_info;
        proc_entry->write_proc = write_info;
        printk(KERN_INFO "procEntry123 created.\n");
    }

    return ret;
}

void cleanup_module( void )
{
    remove_proc_entry("procEntry123", proc_entry);
    printk(KERN_INFO "procEntry123 unloaded.\n");
    vfree(info);
}

ssize_t write_info( struct file *filp, const char __user *buff, unsigned long len, void *data )
{
    int capacity = (MAX_LEN-write_index)+1;
    if (len > capacity)
    {
        printk(KERN_INFO "No space to write in procEntry123!\n");
        return -1;
    }
    if (copy_from_user( &info[write_index], buff, len ))
    {
        return -2;
    }

    write_index += len;
    info[write_index-1] = 0;
    return len;
}

int read_info( char *page, char **start, off_t off, int count, int *eof, void *data )
{
    int len;
    if (off > 0)
    {
        *eof = 1;
        return 0;
    }

    if (read_index >= write_index)
    read_index = 0;

    len = sprintf(page, "%s\n", &info[read_index]);
    read_index += len;
    return len;
}

En el código de arriba:

  • En la función init_module usamos la función 'create_proc_entry' para crear un archivo proc llamado 'procEntry123'
  • El archivo se crea con los privilegios adecuados, tal como se describe en el segundo argumento de la función create_proc_entry.
  • Se utilizan dos funciones read_info y write_info cuando se lee y escribe el archivo proc.
  • La dirección de estas dos funciones se asigna a los miembros de la estructura proc_dir_entry.
  • El paso anterior se realizó para que el código supiera qué función llamar cuando se lee y escribe el archivo proc.
  • En la función write_info, si hay capacidad para escribir en el búfer, la función copy_from_user se usa para copiar la cadena del espacio del usuario al búfer de memoria asignado al módulo del kernel.
  • En la función read_info, la información presente en el búfer se envía de vuelta al espacio del usuario.

El Makefile para el código anterior se ve así:

$ cat Makefile
obj-m += proc.o
all:
        sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Ahora, cuando se compila el código anterior, vemos:

$ make
sudo make -C /lib/modules/2.6.32-21-generic/build M=/home/himanshu modules
make: Entering directory `/usr/src/linux-headers-2.6.32-21-generic'
CC [M]  /home/himanshu/proc.o
/home/himanshu/proc.c: In function ‘init_module’:
/home/himanshu/proc.c:33: warning: assignment from incompatible pointer type
Building modules, stage 2.
MODPOST 1 modules
LD [M]  /home/himanshu/proc.ko
make: Leaving directory `/usr/src/linux-headers-2.6.32-21-generic'

Una vez que el código se compila correctamente, el módulo se inserta y carga con el siguiente comando:

$ sudo insmod proc.ko

Y después de insertar si vemos el directorio proc, encontramos una entrada 'procEntry123'

$ ls /proc/procEntry123
/proc/procEntry123

Ahora, si tratamos de escribir y leer de él:

$ echo "TGS" > /proc/procEntry123
$ cat /proc/procEntry123
TGS

Entonces vemos que podemos leer y escribir el archivo proc. De la misma manera se implementan todos los archivos de proceso estándar.


Linux
  1. Cómo crear un intercambio en Linux

  2. Cómo crear un archivo de intercambio en Linux

  3. Cómo crear un usuario de Linux usando Ansible

  4. Crear archivos usando la línea de comando en Linux

  5. Cómo crear archivos dispersos en Linux usando el comando 'dd'

Cómo crear un archivo en Linux usando el comando Cat

Cómo crear un archivo en Linux usando Terminal

Cómo crear un archivo en Ubuntu Linux usando comando y GUI

Archivos /proc/cpuinfo y /proc/meminfo en Linux

Cómo comprimir un archivo en Linux

Cómo crear archivos zip o directorios protegidos con contraseña en Linux