您的位置 首页 编程

用户与内核空间数据交换的方法之一:procfs

用户与内核空间数据交换的方式之一:procfs-procfs是比较老的一种用户态与内核态的数据交换方式,内核的很多数据都是通过这种方式出口给用户的,内核的很多参数也是通过这种方式来让用户方便设置的。

procfs是比较老的一种用户态与内核态的数据交换方法,内核的许多数据都是经过这种方法出口给用户的,内核的许多参数也是经过这种方法来让用户便利设置的。除了sysctl出口到/proc下的参数,procfs供给的大部分内核参数是只读的。实际上,许多运用严重地依赖于procfs,因而它几乎是必不可少的组件。本节将解说怎么运用procfs。

Procfs供给了如下API: 

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结构的指针。 

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

该函数用于删去上面函数创立的proc条目,参数name给出要删去的proc条目的称号,参数parent指定树立的proc条目地点的目录。 

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

该函数用于创立一个proc目录,参数name指定要创立的proc目录的称号,参数parent为该proc目录地点的目录。 

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

struct proc_dir_entry *proc_symlink(const char * name, struct proc_dir_entry* parent, const char *dest)

该函数用于树立一个proc条目的符号链接,参数name给出要树立的符号链接proc条目的称号,参数parent指定符号衔接地点的目录,参数dest指定链接到的proc条目称号。

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);

该函数用于树立一个规矩的只读proc条目,参数name给出要树立的proc条目的称号,参数mode给出了树立的该proc条目的拜访权限,参 数base指定树立的proc条目地点的目录,参数read_proc给出读去该proc条目的操作函数,参数data为该proc条目的专用数据,它将 保存在该proc条目对应的struct file结构的private_data字段中。

struct proc_dir_entry *create_proc_info_entry(const char *name, mode_t mode, struct proc_dir_entry *base,
get_info_t *get_info);

该函数用于创立一个info型的proc条目,参数name给出要树立的proc条目的称号,参数mode给出了树立的该proc条目的拜访权限, 参数base指定树立的proc条目地点的目录,参数get_info指定该proc条目的get_info操作函数。实际上get_info等同于 read_proc,假如proc条目没有界说个read_proc,对该proc条目的read操作将运用get_info替代,因而它在功用上十分类似于函数create_proc_read_entry。 

struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, get_info_t *get_info)

该函数用于在/proc/net目录下创立一个proc条目,参数name给出要树立的proc条目的称号,参数mode给出了树立的该proc条目的拜访权限,参数get_info指定该proc条目的get_info操作函数。

struct proc_dir_entry *proc_net_fops_create(const char *name, mode_t mode, struct file_operations *fops)

该函数也用于在/proc/net下创立proc条目,可是它也一起指定了对该proc条目的文件操作函数。 

void proc_net_remove(const char *name)

该函数用于删去前面两个函数在/proc/net目录下创立的proc条目。参数name指定要删去的proc称号。
除了这些函数,值得一提的是结构struct proc_dir_entry,为了创立一了可写的proc条目并指定该proc条目的写操作函数,有必要设置上面的这些创立proc条目的函数回来的指针 指向的struct proc_dir_entry结构的write_proc字段,并指定该proc条目的拜访权限有写权限。
为了运用这些接口函数以及结构struct proc_dir_entry,用户有必要在模块中包括头文件linux/proc_fs.h。
在源代码包中给出了procfs示例程序procfs_exam.c,它界说了三个proc文件条目和一个proc目录条目,读者在刺进该模块后应当看到如下结构:

$ ls /proc/myproctest
aint astring bigprocfile
$

读者能够经过cat和echo等文件操作函数来检查和设置这些proc文件。特别需求指出,bigprocfile是一个大文件(超越一个内存
页),关于这种大文件,procfs有一些约束,由于它供给的缓存,只要一个页,因而有必要特别当心,并对超越页的部分做特别的考虑,处理起来比较复杂而且
很简单犯错,一切procfs并不适合于大数据量的输入输出,后边一节seq_file便是由于这一缺点而规划的,当然seq_file依赖于 procfs的一些根底功用。

//kernel module: procfs_exam.c
#include #include #include #include #include #include #include

#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);
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;

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;
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);
return count;
}

int string_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
if (count > STR_MAX_SIZE) {
count = 255;
}
copy_from_user(data, buffer, count);
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”);

 

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/biancheng/90047.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部