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