用户空间与内核空间通讯接口之procfs

概述

procfs是比较老的一种用户态与内核态的数据交换方式,内核的很多数据都是通过这种方式出口给用户的,内核的很多参数也是通过这种方式来让用户方便设置的。除了sysctl出口到/proc下的参数,procfs提供的大部分内核参数是只读的。

创建实例

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

该函数用于创建一个正常的proc条目,参数name给出要建立的proc条目的名称,参数mode给出了建立的该proc条目的访问权限,参数 parent指定建立的proc条目所在的目录。如果要在/proc下建立proc条目,parent应当为NULL。否则它应当为proc_mkdir 返回的struct proc_dir_entry结构的指针。

删除实例

void remove_proc_entry(const char *name, struct proc_dir_entry *parent)

该函数用于删除上面函数创建的proc条目,参数name给出要删除的proc条目的名称,参数parent指定建立的proc条目所在的目录。

创建proc 目录

struct  proc_dir_entry *proc_mkdir(const char * name, struct proc_dir_entry *parent)

该函数用于创建一个proc目录,参数name指定要创建的proc目录的名称,参数parent为该proc目录所在的目录。

可以通过cat和echo等文件操作函数来查看和设置这些proc文件。特别需要指出,bigprocfile是一个大文件(超过一个内存页),对于这种大文件,procfs有一些限制,因为它提供的缓存,只有一个页,因此必须特别小心,并对超过页的部分做特别的考虑,处理起来比较复杂并且很容易出错,所有procfs并不适合于大数据量的输入输出。

实例

Makefile

obj-m := test_procfs.o
test_procfs-objs := procfs.o

KERNELDIR = /lib/modules/$(shell uname -r)/build
#KERNELDIR = /lib/modules/2.6.32-220.el6.x86_64/build
PWD := $(shell pwd)
default:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:  
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/uaccess.h>

#define STR_MAX_SIZE 255
static int int_var;
static char string_var[256];
static char big_buffer[65536];
static int big_buffer_len = 0;
static struct proc_dir_entry * myprocroot;
static int first_write_flag = 1;

int int_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
    count = sprintf(page, "%d", *(int *)data);
    printk("read int %d",count);
    return count;
}

int int_write_proc(struct file *file, const char __user *buffer,unsigned long count, void *data)
{
    unsigned int c = 0, len = 0, val, sum = 0;
    int * temp = (int *)data;

    printk("int write start\r\n");

    while (count) {
    if (get_user(c, buffer)) //从用户空间中得到数据
     return -EFAULT;

    len++;
    buffer++;
    count--;

    if (c == 10 || c == 0)
    break;
    val = c - '0';
    if (val > 9)
    return -EINVAL;
    sum *= 10;
    sum += val;
    }
    * temp = sum;
    printk("int write *tmp = %d", *temp);
    return len;
}

int string_read_proc(char *page, char **start, off_t off,int count, int *eof, void *data)
{
    count = sprintf(page, "%s", (char *)data);
    printk("string_read_proc %s %d",data,count);
    return count;
}

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

    printk("string_write_proc start\r\n");

    if (count > STR_MAX_SIZE) {
    count = 255;
    }
    copy_from_user(data, buffer, count);

    printk("string_write_proc %s", data);
    return count;
}

int bigfile_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
    if (off > big_buffer_len) {
    * eof = 1;
    return 0;
    }

    if (count > PAGE_SIZE) {
    count = PAGE_SIZE;
    }

    if (big_buffer_len - off < count) {
    count = big_buffer_len - off;
    }

    memcpy(page, data, count);
    *start = page;
    return count;

}

int bigfile_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
    char * p = (char *)data;

    if (first_write_flag) {
    big_buffer_len = 0;
    first_write_flag = 0;
    }

    if (65536 - big_buffer_len < count) {
    count = 65536 - big_buffer_len;
    first_write_flag = 1;
    }

    copy_from_user(p + big_buffer_len, buffer, count);
    big_buffer_len += count;
    return count;
}

static int __init procfs_exam_init(void)
{
    #ifdef CONFIG_PROC_FS
    struct proc_dir_entry * entry;
    myprocroot = proc_mkdir("myproctest", NULL);
    entry = create_proc_entry("aint", 0644, myprocroot);
    if (entry) {
    entry->data = &int_var;
    entry->read_proc = &int_read_proc;
    entry->write_proc = &int_write_proc; 
    }


    entry = create_proc_entry("astring", 0644, myprocroot);
    if (entry) {
    entry->data = &string_var;
    entry->read_proc = &string_read_proc;
    entry->write_proc = &string_write_proc; 
    }

    entry = create_proc_entry("bigprocfile", 0644, myprocroot);
    if (entry) {
    entry->data = &big_buffer;
    entry->read_proc = &bigfile_read_proc;
    entry->write_proc = &bigfile_write_proc; 
    }

    #else
    printk("This module requires the kernel to support procfs,\n");
    #endif


    return 0;
}

static void __exit procfs_exam_exit(void)
{
    #ifdef CONFIG_PROC_FS
    remove_proc_entry("aint", myprocroot);
    remove_proc_entry("astring", myprocroot);
    remove_proc_entry("bigprocfile", myprocroot);
    remove_proc_entry("myproctest", NULL);
    #endif
}

module_init(procfs_exam_init);
module_exit(procfs_exam_exit);
MODULE_LICENSE("GPL");

加载
insmod test_procfs.ko

测试
[root@localhost lytest]# cd -
/proc/myproctest
[root@localhost myproctest]# ls
aint astring bigprocfile
[root@localhost myproctest]# echo 1 > aint
[root@localhost myproctest]# cat aint
1
[root@localhost myproctest]# echo “abc” >astring
[root@localhost myproctest]# cat astring
abc
[root@localhost myproctest]# dmesg

卸载
rmmod test_procfs.ko

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值