Learning about proc in the kernel

Learning of proc programming in linux kernel 5.8

Facing the proc_fs.h header file, a little bit of learning

See the first structure in the header file, the operation structure of the /proc directory

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;

Look at the important functions in the header file

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

Okay, write down the first demo

#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

Excuting an order

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

Okay, the entire proc directory collapsed

ls /proc

The entire command line of the computer crashes, click the shutdown button, the machine freezes. . . . . .

What is the reason for this? Caused me to think

The header file of vim prc_fs.h, I think I found the reason

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

This function is commented out, which means it doesn’t work anymore, and the proc_remove function is found in the source code,
but the implementation does not seem to work because there is nothing in the implementation code.

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

Then modify the demo again

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

Execute the command again

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

Seen in the debug ring buffer

[ 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

Uninstall the driver

sudo rmmod proc.ko

Seeing that /proc/our_proc is gone, everything is back to normal

This is the new function api of proc, which is mainly used to dynamically query drive information. Of course, we call the
glibc classic api read write ioctl lseek and so on, which will trigger the corresponding hook

Guess you like

Origin blog.csdn.net/qq_32783703/article/details/113090611