En savoir plus sur proc dans le noyau

Apprentissage de la programmation proc dans le noyau Linux 5.8

Face au fichier d'en-tête proc_fs.h, un peu d'apprentissage

Voir la première structure dans le fichier d'en-tête, la structure des opérations du répertoire / proc

struct proc_ops {
    
    
        unsigned int proc_flags;
        int     (*proc_open)(struct inode *, struct file *);
        ssize_t (*proc_read)(struct file *, char __user *, size_t, loff_t *);
        ssize_t (*proc_write)(struct file *, const char __user *, size_t, loff_t *);
        loff_t  (*proc_lseek)(struct file *, loff_t, int);
        int     (*proc_release)(struct inode *, struct file *);
        __poll_t (*proc_poll)(struct file *, struct poll_table_struct *);
        long    (*proc_ioctl)(struct file *, unsigned int, unsigned long);
#ifdef CONFIG_COMPAT
        long    (*proc_compat_ioctl)(struct file *, unsigned int, unsigned long);
#endif
        int     (*proc_mmap)(struct file *, struct vm_area_struct *);
        unsigned long (*proc_get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
} __randomize_layout;

Regardez les fonctions importantes dans le fichier d'en-tête

extern struct proc_dir_entry *proc_create_data(const char *, umode_t,
                                               struct proc_dir_entry *,
                                               const struct proc_ops *,
                                               void *);

OK, écris la première démo

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h> /* copy_*_user */
#include <linux/slab.h>

int our_proc_open(struct inode *, struct file *);
ssize_t our_proc_read(struct file *, char __user *, size_t, loff_t *);

struct proc_ops ops = {
    
    
        .proc_open = our_proc_open,
        .proc_read = our_proc_read
};

int our_proc_open(struct inode *inode, struct file *file)
{
    
    
    return 0;
};

ssize_t our_proc_read(struct file *file, char __user * buffer, size_t size, loff_t *off_t)
{
    
    
    printk(KERN_ALERT "HELLO,our_proc_read\n");
    return 0;
};

static int __init our_proc_init(void)
{
    
    
    printk(KERN_ALERT "HELLO,KERNEL\n");

    //挂载proc
    proc_create_data("our_proc", 0644, NULL, &ops, NULL);
    return 0;
}

static void __exit our_proc_exit(void)
{
    
    
    printk(KERN_ALERT "HELLO,KERNEL BYE BYE\n");
    remove_proc_entry("our_proc", NULL);
}

module_init(our_proc_init);
module_exit(our_proc_exit);

Makefile

obj-m:=proc.o
        KERNELBUILD := /lib/modules/$(shell uname -r)/build
default:
	        make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
	        rm -rf *.o *.ko

Exécution d'une commande

sudo make
sudo insmod proc.ko
sudo rmmod proc.ko

D'accord, tout le répertoire proc s'est effondré

ls /proc

Toute la ligne de commande de l'ordinateur plante, cliquez sur le bouton d'arrêt, la machine se fige. . . . . .

Quelle est la raison pour ça? M'a fait réfléchir

Le fichier d'en-tête de vim prc_fs.h, je pense avoir trouvé la raison

#define remove_proc_entry(name, parent) do {} while (0)

Cette fonction est commentée, ce qui signifie qu'elle ne fonctionne plus, et la fonction proc_remove se trouve dans le code source,
mais l'implémentation ne semble pas fonctionner car il n'y a rien dans le code d'implémentation.

static inline void proc_remove(struct proc_dir_entry *de) {}

Puis modifiez à nouveau la démo

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h> /* copy_*_user */
#include <linux/slab.h>

#define MODULE_NAME "our_proc"

struct proc_dir_entry* proc_handle = NULL;

int our_proc_open(struct inode *, struct file *);
ssize_t our_proc_read(struct file *, char __user *, size_t, loff_t *);

struct proc_ops ops = {
        .proc_open = our_proc_open,
        .proc_read = our_proc_read
};

int our_proc_open(struct inode *inode, struct file *file)
{
    return 0;
};

ssize_t our_proc_read(struct file *file, char __user * buffer, size_t size, loff_t *off_t)
{
    printk(KERN_ALERT "HELLO,our_proc_read\n");
    return 0;
};

static int __init our_proc_init(void)
{
    printk(KERN_ALERT "HELLO,KERNEL\n");

    //挂载proc
    proc_handle = proc_create_data(MODULE_NAME, 0644, NULL, &ops, NULL);
    return 0;
}

static void __exit our_proc_exit(void)
{
    printk(KERN_ALERT "HELLO,KERNEL BYE BYE\n");
    if (proc_handle) {
        proc_remove(proc_handle);
    }
}

module_init(our_proc_init);
module_exit(our_proc_exit);

Exécutez à nouveau la commande

sudo make
sudo insmod proc.ko
cat /proc/our_proc
dmesg

Vu dans le tampon en anneau de débogage

[ 1212.214871] HELLO,KERNEL
[ 1227.271966] HELLO,our_proc_read
[ 1250.484078] HELLO,KERNEL BYE BYE
[ 1305.898772] HELLO,KERNEL
[ 1342.722686] HELLO,KERNEL BYE BYE
[ 1649.965351] HELLO,KERNEL
[ 1656.079254] HELLO,our_proc_read
[ 1657.011422] HELLO,our_proc_read

Désinstaller le pilote

sudo rmmod proc.ko

Voyant que / proc / our_proc est parti, tout est revenu à la normale

Ceci est la nouvelle fonction api de proc, qui est principalement utilisée pour interroger dynamiquement les informations du pilote. Bien sûr, nous appelons la
glibc classic api read write ioctl lseek et ainsi de suite déclenchera le hook correspondant

Je suppose que tu aimes

Origine blog.csdn.net/qq_32783703/article/details/113090611
conseillé
Classement