Aprendizaje de la programación proc en linux kernel 5.8
Frente al archivo de encabezado proc_fs.h, un poco de aprendizaje
Vea la primera estructura en el archivo de encabezado, la estructura de operación del directorio / 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;
Mira las funciones importantes en el archivo de encabezado
extern struct proc_dir_entry *proc_create_data(const char *, umode_t,
struct proc_dir_entry *,
const struct proc_ops *,
void *);
De acuerdo, escribe la primera demostración
#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
Ejecutando una orden
sudo make
sudo insmod proc.ko
sudo rmmod proc.ko
Bien, todo el directorio proc colapsó
ls /proc
Toda la línea de comando de la computadora se bloquea, haga clic en el botón de apagado, la máquina se congela. . . . . .
¿Cuál es la razón para esto? Me hizo pensar
El archivo de encabezado de vim prc_fs.h, creo que encontré la razón
#define remove_proc_entry(name, parent) do {} while (0)
Esta función está comentada, lo que significa que ya no funciona, y la función proc_remove se encuentra en el código fuente,
pero la implementación no parece funcionar porque no hay nada en el código de implementación.
static inline void proc_remove(struct proc_dir_entry *de) {}
Luego modifique la demostración nuevamente
#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);
Ejecute el comando nuevamente
sudo make
sudo insmod proc.ko
cat /proc/our_proc
dmesg
Visto en el búfer de anillo de depuración
[ 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
Desinstalar el controlador
sudo rmmod proc.ko
Al ver que / proc / our_proc se ha ido, todo vuelve a la normalidad
Esta es la nueva función api de proc, que se usa principalmente para consultar dinámicamente la información del controlador. Por supuesto, llamamos a la
API clásica glibc read write ioctl lseek y así sucesivamente activará el gancho correspondiente