天天看點

proc檔案系統接口

核心提供的proc接口函數

頭檔案linux/proc_fs.h

struct proc_dir_entry *​

​proc_mkdir​

​​(const char *name, struct proc_dir_entry *parent);

在parent目錄建立一個名為name的目錄

struct proc_dir_entry *​

​create_proc_entry​

​​(const char *name, mode_t mode, struct proc_dir_entry *parent);

在parent目錄建立一個名為name,權限為mode的檔案

在create_proc_entry函數執行後傳回struct proc_dir_entry可以自己指定read, write等函數

struct proc_dir_entry* ​

​create_proc_read_entry​

​(const char name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void data);

如果隻需要read函數,可以使用他,他其實是對create_proc_entry進行了封裝,把create_proc_read_entry的傳入值read_proc賦給了create_proc_entry傳回值的read_proc成員。

struct proc_dir_entry *​

​proc_create​

​​(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops)

新的核心版本中,至少在3.10核心中已經看不到create_proc_entry了,取而代之的是使用proc_create建立檔案,proc_create中需要指定proc_fops中的read和write等方法,以友善使用者空間的操作。

struct proc_dir_entry *​

​proc_symlink​

​​(const char *name, struct proc_dir_entry *parent, const char *dest);

在parent目錄建立指定dest目錄的名為name的符号連結。

void ​

​remove_proc_entry​

​​( const char *name, struct proc_dir_entry *parent );

删除parent目錄中名為name的檔案或者目錄。

使用proc接口函數例子

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>

#ifndef LINUX_VERSION_CODE
#define LINUX_VERSION_CODE 199163       /* kernel version 3.10 */
#endif

#ifndef KERNEL_VERSION(a, b, c)
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#endif

#define STRINGLEN 1024
char global_buffer[STRINGLEN] = "hello";
struct proc_dir_entry *example_dir, *data_file;

#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
int proc_read_hello(char *page, char **start, off_t off, int count,
                int *eof, void *data)
{
        int len;
        len = sprintf(page, global_buffer); //把global_buffer的内容顯示給通路者

        return len;
}

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

        if (count >= STRINGLEN)
                len = STRINGLEN - 1;
        else
                len = count;

        /*
         * copy_from_user函數将資料從使用者空間拷貝到核心空間
         * 此處将使用者寫入的資料存入global_buffer
         */
        copy_from_user(global_buffer, buffer, len);
        global_buffer[len] = '\0';

        return len;
}
#else
static ssize_t proc_read(struct file *file, char __user *buf,
                        size_t count, loff_t *ppos)
{
        int len;

        if (*ppos > 0)
                return 0;

        len = strlen(global_buffer) + 1;
        if (copy_to_user(buf, global_buffer, len))
                return -EFAULT;

        *ppos += len;

        return len;
}

static ssize_t proc_write(struct file *file, const char __user *buf,
                         size_t count, loff_t *ppos)
{
        int len;

        if (count >= STRINGLEN)
                len = STRINGLEN - 1;
        else
                len = count;

        if (copy_from_user(global_buffer, buf, len))
                return -EFAULT;

        global_buffer[len] = '\0';

        return len;
}

static const struct file_operations proc_fops = {
        .owner = THIS_MODULE,
        .read = proc_read,
        .write = proc_write,
};
#endif

static int __init proc_test_init(void)
{
        example_dir = proc_mkdir("proc_test", NULL);

#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
        data_file = create_proc_entry("data", S_IRUGO, example_dir);
        data_file->read_proc = proc_read_hello;
        data_file->write_proc = proc_write_hello;
#else
        data_file = proc_create("data", S_IRUGO, example_dir, &proc_fops);
#endif
        return 0;
}

static void __exit proc_test_exit(void)
{
        remove_proc_entry("data", example_dir);
        remove_proc_entry("proc_test", NULL);
}

module_init(proc_test_init);
module_exit(proc_test_exit);      

參考文章

參考資源

繼續閱讀