Linux设备驱动---/proc文件系统

本文介绍如何在 Linux 中创建、删除及读写 proc 文件系统中的文件。通过示例代码展示了使用 proc_mkdir 和 create_proc_entry 创建目录与文件的方法,以及如何通过实现 read_proc 和 write_proc 回调函数来支持文件的读写操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

in Linux, proc文件系统是一个虚拟文件系统,用户和应用程序可以通过proc文件系统得到当前的一些系统信息,并可以改变一些内核的参数。/proc下的文件是一种特殊文件,不能够像一般文件一样创建删除。下面讨论proc文件的创建、删除与读写。

1.创建目录:

  1. struct proc_dir_entry *proc_mkdir(const char *name,  
  2.                 struct proc_dir_entry *parent);  

2.创建proc文件:

  1. struct proc_dir_entry *create_proc_entry( const char *name,  mode_t mode,  
  2.                 struct proc_dir_entry *parent );  

create_proc_entry函数用于创建一个一般的proc文件,其中name是文件名,比如“hello”,mode是文件模式,parent是要创建的proc文件的父目录(若parent = NULL则创建在/proc目录下)。

3.删除proc文件/目录:

  1. void remove_dir_entry(const char *name, struct proc_dir_entry *parent);  

参数同proc_mkdir()函数类似

4.创建可读写的proc文件

proc文件实际上是一个叫做proc_dir entry的struct(定义在proc_fs.h),该struct中有int read_proc和int write_proc两个元素,要实现proc的文件的读写就要给这两个元素赋值。但这里不是简单地将一个整数赋值过去就行了,需要实现两个回调函数。

在用户或应用程序访问该proc文件时,就会调用这个函数,实现这个函数时只需将想要让用户看到的内容放入page即可。

写回调函数原型:int mod_write( struct file *filp, const char __user *buff, unsigned long len, void *data );

在用户或应用程序试图写入该proc文件时,就会调用这个函数,实现这个函数时需要接收用户写入的数据(buff参数)。


写一个模块测试proc文件的读写:

  1. #include linux/module.h  
  2. #include linux/kernel.h  
  3. #include linux/proc_fs.h  
  4. #include linux/sched.h  
  5. #include asm/uaccess.h  
  6.    
  7. #define STRINGLEN 1024  
  8.    
  9. char global_buffer[STRINGLEN];  
  10.    
  11. struct proc_dir_entry *example_dir, *hello_file;  
  12.    
  13. int proc_read_hello(char *page, char **start, off_t off, int count, int *eof,  
  14.                 void *data) {  
  15.         int len;  
  16.         len = sprintf(page, global_buffer); //把global_buffer的内容显示给访问者  
  17.         return len;  
  18. }  
  19.    
  20. int proc_write_hello(struct file *file, const char *buffer, unsigned long count,  
  21.                 void *data) {  
  22.         int len;  
  23.    
  24.         if (count = STRINGLEN)  
  25.                 len = STRINGLEN – 1;  
  26.         else  
  27.                 len = count;  
  28.    
  29.         /* 
  30.          * copy_from_user函数将数据从用户空间拷贝到内核空间 
  31.          * 此处将用户写入的数据存入global_buffer 
  32.          */  
  33.         copy_from_user(global_buffer, buffer, len);  
  34.         global_buffer[len] = \0′;  
  35.         return len;  
  36. }  
  37.    
  38. static int __init proc_test_init(void) {  
  39.         example_dir = proc_mkdir("proc_test", NULL);  
  40.         hello_file = create_proc_entry("hello", S_IRUGO, example_dir);  
  41.         strcpy(global_buffer, "hello");  
  42.         hello_file->read_proc = proc_read_hello;  
  43.         hello_file->write_proc = proc_write_hello;  
  44.         return 0;  
  45. }  
  46.    
  47. static void __exit proc_test_exit(void) {  
  48.         remove_proc_entry("hello", example_dir);  
  49.         remove_proc_entry(“proc_test”, NULL);  
  50. }  
  51.    
  52. module_init(proc_test_init);  
  53. module_exit(proc_test_exit);  


写入proc文件

echo "Hello from kernel" /proc/proc_test/hello'

读取proc文件内容,将看到屏幕上显示了我们写入的字符串:Hello from kernel

cat /proc/proc_test/hello
 
关于seq_file接口(创建虚拟文件容量大于1页的接口)的例子:
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>

static struct proc_dir_entry *pfile;

static char *myfruits[5] = {"apple", "orange", "banana", "watermelon", "pear"};

static void *my_seq_start(struct seq_file *s, loff_t *pos)
{
        if (*pos >= 5)
                return NULL;
        return myfruits[*pos];
}

static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
        if (++*pos >= 5)
                return NULL;
        return myfruits[*pos];
}

static void my_seq_stop(struct seq_file *s, void *v)
{
    // nothing to do;
}

static int my_seq_show(struct seq_file *s, void *v)
{
        seq_printf(s, "%s ", (char *)v);
        return 0;
}

static struct seq_operations proc_seq_ops = {
        .start = my_seq_start,
        .next = my_seq_next,
        .stop = my_seq_stop,
        .show = my_seq_show,
};

static int my_seq_open(struct inode *inode, struct file *file)
{
        return seq_open(file, &proc_seq_ops);
}

static struct file_operations proc_fops = {
        .open = my_seq_open,
        .read = seq_read,
        .llseek = seq_lseek,
        .release = seq_release,
};

static int __init myproc_init(void)
{
        pfile = proc_create("fruits", 0666, NULL, &proc_fops);
        if (!pfile) {
                printk(KERN_ERR "Can't create /proc/fruits/n");
                remove_proc_entry("mydir", NULL);
                return -1;
        }

        return 0;
}

static void __exit myproc_exit(void)
{
        remove_proc_entry("fruits", NULL);
}

module_init(myproc_init);
module_exit(myproc_exit);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值