【问题标题】:Explanation of LKM and procfsLKM和procfs的解释
【发布时间】:2014-04-15 13:07:58
【问题描述】:

我正在学习用于将数据从内核读取到用户空间的 proc 和可加载内核模块 (LKM)。 I asked for some info regarding procfs in another post.

谁能告诉我 lkm 和 procfs 是什么,我可以在哪里编写 lkm 和 proc 的代码(在内核源代码中的位置)?

【问题讨论】:

    标签: c linux linux-kernel kernel proc


    【解决方案1】:

    您不会在内核源代码中为 LKM 编写代码(尽管有可能,但不建议这样做,除非您正在处理将成为正常分布的模块)。相反,您可以创建自己的目录并提供代码。

    您为提供 procfs 接口而编写的函数只是您的 LKM 源代码的一部分。

    http://linux.die.net/lkmpg/x769.html 有一个使用 procfs 的简单示例,在此转载:

    /**
     *  procfs2.c -  create a "file" in /proc
     *
     */
    
    #include <linux/module.h>   /* Specifically, a module */
    #include <linux/kernel.h>   /* We're doing kernel work */
    #include <linux/proc_fs.h>  /* Necessary because we use the proc fs */
    #include <asm/uaccess.h>    /* for copy_from_user */
    
    #define PROCFS_MAX_SIZE     1024
    #define PROCFS_NAME         "buffer1k"
    
    /**
     * This structure hold information about the /proc file
     *
     */
    static struct proc_dir_entry *Our_Proc_File;
    
    /**
     * The buffer used to store character for this module
     *
     */
    static char procfs_buffer[PROCFS_MAX_SIZE];
    
    /**
     * The size of the buffer
     *
     */
    static unsigned long procfs_buffer_size = 0;
    
    /** 
     * This function is called then the /proc file is read
     *
     */
    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) called\n", PROCFS_NAME);
    
        if (offset > 0) {
            /* we have finished to read, return 0 */
            ret  = 0;
        } else {
            /* fill the buffer, return the buffer size */
            memcpy(buffer, procfs_buffer, procfs_buffer_size);
            ret = procfs_buffer_size;
        }
    
        return ret;
    }
    
    /**
     * This function is called with the /proc file is written
     *
     */
    int procfile_write(struct file *file, const char *buffer, unsigned long count,
               void *data)
    {
        /* get buffer size */
        procfs_buffer_size = count;
        if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
            procfs_buffer_size = PROCFS_MAX_SIZE;
        }
    
        /* write data to the buffer */
        if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
            return -EFAULT;
        }
    
        return procfs_buffer_size;
    }
    
    /**
     *This function is called when the module is loaded
     *
     */
    int init_module()
    {
        /* create the /proc file */
        Our_Proc_File = create_proc_entry(PROCFS_NAME, 0644, NULL);
    
        if (Our_Proc_File == NULL) {
            remove_proc_entry(PROCFS_NAME, &proc_root);
            printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
                PROCFS_NAME);
            return -ENOMEM;
        }
    
        Our_Proc_File->read_proc  = procfile_read;
        Our_Proc_File->write_proc = procfile_write;
        Our_Proc_File->owner      = THIS_MODULE;
        Our_Proc_File->mode       = S_IFREG | S_IRUGO;
        Our_Proc_File->uid    = 0;
        Our_Proc_File->gid    = 0;
        Our_Proc_File->size       = 37;
    
        printk(KERN_INFO "/proc/%s created\n", PROCFS_NAME);    
        return 0;   /* everything is ok */
    }
    
    /**
     *This function is called when the module is unloaded
     *
     */
    void cleanup_module()
    {
        remove_proc_entry(PROCFS_NAME, &proc_root);
        printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME);
    }
    

    模块初始化使用create_proc_entry() 建立一个procfs 条目。函数procfile_writeprocfile_read 被初始化以处理对该条目的写入和读取。模块的cleanup_module() 函数在模块卸载时调用,通过调用cleanup_module() 删除procfs 条目。


    您可以在http://www.cyberciti.biz/tips/compiling-linux-kernel-module.html 找到构建内核模块的教程。总结如下:

    1) 确保您在 /usr/src 中安装了内核源代码。

    2) 创建一个如下所示的 makefile:

    obj-m = procfs2.o
    KVERSION = $(shell uname -r)
    all:
            make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
    clean:
            make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
    

    3) 使用命令make 构建模块 4) 使用命令insmod procfs2.ko 将模块加载到内存中(以root 用户身份执行此操作)

    教程中未列出的是:如果您的模块有问题,请重新启动。内核模块中的崩溃通常会导致您的系统崩溃。

    【讨论】:

    • 非常感谢。然后我将在/proc目录中添加上面的代码作为procfs2.c。这样对吗 ??这个 procfs2.c 充当用户和内核之间的接口。对吗??
    • 我修改了内核代码并计算了时间戳。稍后我想将时间戳从内核写入用户空间。那么你能告诉我我该怎么做吗? stackoverflow.com/questions/23080920/…
    • 你不要在 /proc 中添加文件... /proc 并不是一个真正的文件系统,它只是一个看起来像一个的接口。您加载一个在 /proc 中创建伪文件的模块,客户端应用程序通过读取和写入该文件与您的模块进行交互。
    • 对不起,我很困惑,那么我应该在哪里编写和存储上述代码?加载一个模块只不过是将上面的代码安装到 /proc ??
    • 任何你想要的地方。你把你的资源放在哪里并不重要。将它放在内核源代码树中可能不是一个好主意,但没有什么能阻止你。您选择的位置仅在您构建模块时才重要 - 它的重要性在于它只对您重要,而不是对任何人/任何其他人。
    猜你喜欢
    • 1970-01-01
    • 2012-04-16
    • 2015-07-02
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多