The seq_file interface of Linux kernel study notes creates readable and writable proc files


Study notes and personal understanding. If there are any mistakes, please correct me.

Reminder: It is recommended to read the code in the order of the numbers in the comments

Test method: cat /proc/abc_proc

                   echo any string>/proc/abc_pro (requires root privilege)


/*************************************************
 An example of using the seq_file interface to implement readable and writable proc files
 For kernels after 3.10
 Author: ZhangN
 Date: 2015-5-17
 *************************************************/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>

static char *str = NULL;

/*5, implement the show function
  The role is to output kernel data to user space
  will be called on proc file output */
static int my_proc_show(struct seq_file *m, void *v)
{
    /* Functions like printfk cannot be used here
      A special set of functions to output using seq_file
      See page 91 of ldd3 for details */
    seq_printf(m, "current kernel time is %ld\n", jiffies);
    seq_printf(m, "str is %s\n", str);
    return 0;
}



/*3, implement open and write functions */
static ssize_t my_proc_write(struct file *file, const char __user *buffer,
                             size_t count, loff_t *f_pos)
{
    char *tmp = kzalloc((count+1), GFP_KERNEL);
    if(!tmp)
        return -ENOMEM;
    if(copy_from_user(tmp, buffer, count))
    {
        kfree(tmp);
        return EFAULT;
    }
    kfree(str);
    str = tmp;
    return count;
}

static int my_proc_open(struct inode *inode, struct file *file)
{
    /*4, call single_open in the open function to bind the seq_show function pointer
      It should be noted that the seq interface introduced in ldd3 uses this to call the seq_open function
      Its calling form is as follows:
      return sep_open(file, &scull_seq_ops);
      scull_seq_ops is a struct seq_operations structure
      Bind the show function pointer in the structure
      Need to prepare seq_operations structure
      To call the single_open function, you only need to directly specify the function pointer of show.
      Personal guess may be that the seq_operations structure is implemented in the single_open function
      As for whether it is not known, I did not check the specific implementation
      Interested students can refer to the document: Documentation\filesystems\seq_file.txt
      Regarding the third parameter, its type should be viod*,
      NULL passed in some places in the kernel, inode->i_private passed in in some places, and other values ​​passed in
      Let's see how data is used in the single_open function:
        if (!res)
         ((struct seq_file *)file->private_data)->private = data;
      data is a private member of the seq_file structure.
      So how is data actually used?
      It is found that the first parameter of the show function is of type seq_file. In the show function,
      You can convert the private member of seq_file to the corresponding type for use.
      That is, the data parameter can be passed to the show function through the private member of seq_file */
    return single_open(file, my_proc_show, NULL);
}

/*2, fill in the flie_operations structure called in the proc_create function
  The function at the beginning of my is the function implemented by itself,
  The beginning of seq and single is a good function for the kernel, just fill it in directly
  open is a function that must be filled
  See page 93 of ldd3 here for details */
static struct file_operations my_fops = {
    .owner   = THIS_MODULE,
    .open    = my_proc_open,
    .release = single_release,
    .read    = seq_read,
    .llseek  = seq_lseek,
    .write   = my_proc_write,
};

static int __init my_init(void)
{
    struct proc_dri_entry *file;
    /* New interface for the kernel's proc file after 3.10
      Need to associate file_operations*/
    /*1, first call the function that creates the proc file, you need to bind flie_operations*/
    file = proc_create("abc_proc", 0644, NULL, &my_fops);
    if(!file)
        return -ENOMEM;
    return 0;
}

/*6, delete the proc file */
static void __exit my_exit(void)
{
    remove_proc_entry("abc_proc", NULL);
    kfree(str);
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZhangN");

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325460568&siteId=291194637