简体   繁体   English

通过调用内核模块写入proc文件/给出参数

[英]Writing to proc file / give parameter by calling kernel module

I'm supposed to change a configuration parameter of the kernel by using a kernel module. 我应该通过使用内核模块来更改内核的配置参数。 The kernel module should create a proc file and then I should be able to change the parameter by using the cat command, eg cat "foobar" > /proc/prompt is supposed to set the parameter to "foobar", where prompt is the name of the proc file that was created in the module. 内核模块应该创建一个proc文件,然后我应该能够通过使用cat命令来更改参数,例如cat“ foobar”> / proc / prompt应该将参数设置为“ foobar”,其中提示符是名称在模块中创建的proc文件的名称。

Furthermore I should be able to initialize the parameter by passing it as an argument when calling the module. 此外,我应该能够在调用模块时通过将其作为参数传递来初始化参数。

These two articles were basically the only relevant sources that I have found: 基本上,这两篇文章是我发现的唯一相关资料:

http://www.tldp.org/LDP/lkmpg/2.6/html/x769.html for writing to a proc file and http://www.tldp.org/LDP/lkmpg/2.6/html/x323.html for initializing the parameter from the command line. http://www.tldp.org/LDP/lkmpg/2.6/html/x769.html用于写入proc文件, http ://www.tldp.org/LDP/lkmpg/2.6/html/x323.html用于写入proc文件从命令行初始化参数。

Now I have a couple of questions, first of all this is the module thus far: 现在我有几个问题,首先是到目前为止的模块:

#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/proc_fs.h>

#include "sar_main.h"

#define PROCFS_NAME "sarlkm"

char procfs_buffer[PROCFS_MAX_SIZE];

static unsigned long procfs_buffer_size = 0

struct proc_dir_entry *proc_file_entry;


int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data){
    int ret;

    printk(KERN_INFO "procfile_read (/proc/%s) aufgerufen \n",  PROCFS_NAME);

    if (offset > 0){
        ret = 0;
    }
    else{
        memcpy(buffer, procfs_buffer, procfs_buffer_size);
        ret = procfs_buffer_size;
    }
    return ret;
}

int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data){

    procfs_buffer_size = count;
    if (procfs_buffer_size > PROCFS_MAX_SIZE){
        procfs_buffer_size = PROCFS_MAX_SIZE;
    }
    if ( copy_from_user(procfs_buffer, buffer, procfs_buffer)){
        return -EFAULT;
    }
    return procfs_buffer_size;
}




static int __init sar_init(void)
{
    prompt_proc = create_proc_entry(PROCFS_NAME, 0644, NULL);

    if (prompt_proc = NULL){
        remove_proc_entry(PROCFS_NAME, &proc_root);
        printk(KERN_ALERT "Error: Konnte proc file nicht kreieren")
        return -ENOMEM;
    }

    prompt_proc->read_proc = procfile_read;
    prompt_proc->write_proc = procfile_write;

    printk(KERN_INFO "proc/%s wurde erfolgreich kreiert", PROCFS_NAME);
    return 0;
}

static void __exit sar_cleanup(void)
{
    remove_proc_entry(PROCFS_NAME, &proc_root);
    printk(KERN_INFO "proc/%s gelöscht", PROCFS_NAME);
}

module_init(sar_init);
module_exit(sar_cleanup);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

I think I should say that I don't really understand why the read and write functions are supposed to work when using the cat command. 我想我应该说我不太明白为什么使用cat命令时读取和写入功能应该起作用。 My main question is where exactly is the configuration parameter stored in the proc file? 我的主要问题是proc文件中的配置参数到底存储在哪里? If I would write "foobar" to the proc file using cat and then use cat proc/prompt to read the parameter, how does the read function actually get the new value of the parameter, ie where is "foobar" stored in the procfile? 如果我要使用cat将“ foobar”写入proc文件,然后使用cat proc / prompt读取参数,那么read函数实际上如何获取参数的新值,即procfile中存储的“ foobar”在哪里?

If I would try to initialize the parameter using a command line argument I would have to use a global variable in which to store the value of the parameter, but then how could I use that global variable in the read function, so that cat proc/prompt actually gives out the value that was given to the module from the command line? 如果我尝试使用命令行参数来初始化参数,则必须使用一个全局变量来存储参数的值,但是我该如何在read函数中使用该全局变量,以便cat proc /提示实际上给出了从命令行给模块的值?

The cat command internally calls the read() system call to read data from a file (see man strace ). cat命令在内部调用read()系统调用以从文件读取数据(请参见man strace )。

read() passes the arguments to the VFS and the VFS finally calls your custom procfile_read() routine with the passed arguments (and some additional ones passed by the VFS code). read()将参数传递给VFS ,VFS最终使用传递的参数(以及VFS代码传递的一些其他参数procfile_read()调用自定义procfile_read()例程。 If you want to know more about this, look at the fs directory in kernel sources, especially file read_write.c . 如果您想了解更多信息,请查看内核源代码中的fs目录,尤其是文件read_write.c

Your particular reading function copies, if some conditions are met, the parameter value (which is stored in procfs_buffer to answer one of your questions) into the user-supplied buffer allocated by cat , which is called buffer in your particular code. 如果满足某些条件,您的特定读取函数procfs_buffer参数值(存储在procfs_buffer以回答您的一个问题) procfs_buffercat分配的用户提供的缓冲区中,该buffer在您的特定代码中称为buffer It is the same one as passed by the read() system call like in: 它与read()系统调用传递的内容相同,例如:

read(proc_fd, userspace_buf, 10);    /* userspace_buf is buffer! */

Error checking omitted for clearness's sake. 为了清楚起见,省略了错误检查。

To pass the value to the proc file you have two options: 要将值传递到proc文件,您有两个选择:

  • Use module_param() and write it to your buffer; 使用module_param()并将其写入缓冲区; can only be done once because the module is only loadable once (or unload/reload it every time you want to change the parameter but that sounds inconvenient) 只能执行一次,因为该模块只能加载一次 (或者每次您想更改参数时都卸载/重新加载它,但这听起来很不方便)
  • Invoke write() from userspace (like in cat ) and modify the buffer as often as you want to (this is currently used by your code) 调用write()从用户空间(如在cat )和经常你想 (这是目前使用的代码)修改缓冲区

BTW, I really think your reading function should check the pointer to the user data, ie use copy_to_user() , not memcpy() . 顺便说一句,我真的认为您的阅读功能应该检查指向用户数据的指针,即使用copy_to_user() ,而不是memcpy()

For further information, read Linux Device Drivers . 有关更多信息,请阅读Linux设备驱动程序 There's only an old edition available at the moment but an updated one is being written. 目前只有一个旧版本,但正在编写更新版本。

you can treat xxx_write or xxx_read in driver just as a interface implement, 您可以将驱动程序中的xxx_writexxx_read视为接口工具,

when you call write or read in user space, the kernel will invoke xxx_write or xxx_read in kernel space. 当您在用户空间中调用writeread时,内核将在内核空间中调用xxx_writexxx_read

so you need to store it yourself when write call, 因此您在write电话时需要自己存储它,
and fetch them back when read call, 并在read呼叫时取回它们,
in xxx_write xxx_read xxx_write xxx_read

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM