GNU/Linux >> LINUX-Kenntnisse >  >> Linux

So erstellen Sie Linux-Proc-Dateien im C-Programm mit LKM

Das Proc-Dateisystem spiegelt den aktuellen Stand des Linux-Kernels wider.

Der aktuelle Status des Kernels könnte verschiedene Informationen darstellen, wie die darauf laufenden Prozesse, die Hardwareinformationen, die Netzwerkinformationen usw. Dieses System ist also so konzipiert, dass auf alle diese Informationen von den Prozessen auf Benutzerebene leicht zugegriffen werden kann.

Wir sagen auch, dass ein Proc-Dateisystem ein Pseudo-Dateisystem ist. Dies liegt daran, dass die Dateien in diesem Dateisystem mit Informationen geladen werden, wenn auf diese Dateien zugegriffen wird, und deshalb weisen die Dateien in diesem Dateisystem normalerweise eine Größe von Null auf.

Führen Sie ein ls /proc auf Ihrem System aus und Sie werden etwas Ähnliches wie das Folgende bemerken:

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

Wir sehen also, dass dieses Dateisystem sowohl Dateien als auch Verzeichnisse enthält. Die Namen von Dateien oder Verzeichnissen sind entweder alphabetisch oder numerisch. Die numerischen Datei- oder Verzeichnisnamen entsprechen meistens den Prozessen, die auf dem System ausgeführt werden, und die Zahl stellt die Prozess-ID des Prozesses dar. Es ist also sehr einfach, Informationen auf Kernel-Ebene über jeden Prozess zu erfahren, indem man seine Prozess-ID verwendet und die entsprechende Datei öffnet.

In diesem Artikel bauen wir auf unserem Wissen über Loadable Kernel Modules (LKM) auf und erörtern, wie diese proc-Dateien erstellt, gelesen und geschrieben werden.

Lesen Sie unseren früheren Artikel über das Linux-Proc-Dateisystem, um die verschiedenen Dateien zu verstehen, die sich unter /proc befinden.

Proc-Dateien erstellen

Im Artikel über Linux-Kernel-Module haben wir besprochen, wie LKMs erstellt, geladen und entladen werden. Das war das Grundkonzept, um dem Linux-Kernel zur Laufzeit mehr Funktionalität hinzuzufügen. Proc-Dateien funktionieren nach dem gleichen Prinzip. Jede proc-Datei wird in Form eines LKM erstellt, geladen und entladen.

Im folgenden Code versuchen wir, eine proc-Datei zu erstellen und ihre Lese- und Schreibfähigkeiten zu definieren.

#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;
}

Im Code oben:

  • In der Funktion init_module haben wir die Funktion „create_proc_entry“ verwendet, um eine proc-Datei mit dem Namen „procEntry123“ zu erstellen
  • Die Datei wird mit geeigneten Rechten erstellt, wie durch das zweite Argument der create_proc_entry-Funktion beschrieben.
  • Zwei Funktionen read_info und write_info werden verwendet, wenn die proc-Datei gelesen und geschrieben wird.
  • Die Adresse dieser beiden Funktionen wird Mitgliedern der Struktur proc_dir_entry zugewiesen.
  • Der obige Schritt wurde ausgeführt, damit der Code weiß, welche Funktion aufgerufen werden soll, wenn die proc-Datei gelesen und geschrieben wird.
  • In der Funktion write_info wird, wenn Kapazität zum Schreiben in den Puffer vorhanden ist, die Funktion copy_from_user verwendet, um die Zeichenfolge aus dem Benutzerbereich in den vom Kernelmodul zugewiesenen Speicherpuffer zu kopieren.
  • In der Funktion read_info werden die im Puffer vorhandenen Informationen an den Benutzerbereich zurückgesendet.

Das Makefile für den obigen Code sieht folgendermaßen aus:

$ 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

Wenn der obige Code nun kompiliert ist, sehen wir :

$ 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'

Sobald der Code erfolgreich kompiliert wurde, wird das Modul eingefügt und durch den folgenden Befehl geladen:

$ sudo insmod proc.ko

Und nach dem Einfügen, wenn wir das Proc-Verzeichnis sehen, finden wir einen Eintrag ‚procEntry123‘

$ ls /proc/procEntry123
/proc/procEntry123

Wenn wir nun versuchen, daraus zu schreiben und zu lesen:

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

Wir sehen also, dass wir in der Lage sind, die proc-Datei zu lesen und zu schreiben. Auf die gleiche Weise werden alle Standardproc-Dateien implementiert.


Linux
  1. So erstellen Sie einen Swap unter Linux

  2. So erstellen Sie eine Auslagerungsdatei unter Linux

  3. So erstellen Sie einen Linux-Benutzer mit Ansible

  4. Erstellen Sie Dateien mithilfe der Befehlszeile in Linux

  5. So erstellen Sie Sparse-Dateien in Linux mit dem Befehl „dd“.

So erstellen Sie eine Datei unter Linux mit dem Cat-Befehl

So erstellen Sie eine Datei in Linux mit Terminal

So erstellen Sie eine Datei in Ubuntu Linux mit Befehl und GUI

/proc/cpuinfo- und /proc/meminfo-Dateien unter Linux

So komprimieren Sie eine Datei unter Linux

So erstellen Sie eine passwortgeschützte Zip-Datei oder Verzeichnisse in Linux