
正文
ubuntu/linux mint 创建proc文件的三种方法(四)
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
在做内核驱动开发的时候,能够使用/proc下的文件,获取对应的信息,以便调试。
大多数/proc下的文件是仅仅读的,但为了演示样例的完整性,都提供了写方法。
方法一:使用create_proc_entry创建proc文件(简单,但写操作有缓冲区溢出的危急);
方法二:使用proc_create和seq_file创建proc文件(较方法三简洁);
方法三:使用proc_create_data和seq_file创建proc文件(较麻烦,但比較完整);
演示样例四:在proc文件里使用内核链表的一个演示样例(用的方法三)。
--------------------------------------------------------------------------------------------------------------------
四、
proc_test04.c 源代码
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/slab.h>struct proc_head
{
struct list_head lhead;
int item_count;
int str_count;
};struct proc_item
{
struct list_head litem;
char *buf;
int num;
};struct proc_head *gp_head;// linux/seq_file.h
// void * (*start) (struct seq_file *m, loff_t *pos);
// void (*stop) (struct seq_file *m, void *v);
// void * (*next) (struct seq_file *m, void *v, loff_t *pos);
// int (*show) (struct seq_file *m, void *v);/**
* author: aran
* fuction: seq_operations -> start
*/
static void *my_seq_start(struct seq_file *m, loff_t *pos)
{
struct proc_item *entry;if (0 == *pos)
{
seq_printf(m, "List has %d items, total %d bytes\n", gp_head->item_count, gp_head->str_count);
}// get first item
++*pos;
list_for_each_entry(entry, &gp_head->lhead, litem)
{
if (*pos == entry->num)
{
return entry;
}
}
return NULL;
}/**
* author: aran
* fuction: seq_operations -> next
*/
static void *my_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
struct proc_item *entry;// get next item
++*pos;
list_for_each_entry(entry, &gp_head->lhead, litem)
{
if (*pos == entry->num)
{
return entry;
}
}
return NULL;
}/**
* author: aran
* fuction: seq_operations -> stop
*/
static void my_seq_stop(struct seq_file *m, void *v)
{
// clean sth.
// nothing to do
}/**
* author: aran
* fuction: seq_operations -> show
*/
static int my_seq_show(struct seq_file *m, void *v)
{
struct proc_item *tmp = v;
seq_printf(m, "%s", tmp->buf);return 0;
}// global var
static struct seq_operations my_seq_fops =
{
.start= my_seq_start,
.next= my_seq_next,
.stop= my_seq_stop,
.show= my_seq_show,
};// file_operations
// int (*open) (struct inode *, struct file *)
// ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)/**
* author: aran
* fuction: file_operations -> open
*/
static int proc_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &my_seq_fops);
}/**
* author: aran
* fuction: file_operations -> write
*/
static ssize_t proc_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
struct proc_item *tmp;
int ret;// allocate proc_item
tmp = (struct proc_item *)kzalloc(sizeof(*tmp), GFP_KERNEL);
if (NULL == tmp)
{
ret = -ENOMEM;
goto err_kzalloc1;
}
INIT_LIST_HEAD(&tmp->litem);// allocate str buf
tmp->buf = (char *)kzalloc(count, GFP_KERNEL);
if (NULL == tmp->buf)
{
ret = -ENOMEM;
goto err_kzalloc2;
}if (0 != copy_from_user(tmp->buf, buffer, count))
{
ret = -1;
goto err_copy;
}list_add(&tmp->litem, &gp_head->lhead);
gp_head->item_count++;
gp_head->str_count += count;
tmp->num = gp_head->item_count; return count;err_copy:
kfree(tmp->buf);
err_kzalloc2:
kfree(tmp);
err_kzalloc1:
return ret;
}// global var
static struct file_operations proc_seq_fops =
{
.owner= THIS_MODULE,
.open= proc_seq_open,
.read= seq_read,
.write= proc_seq_write,
.llseek= seq_lseek,
.release= seq_release,
};static int __init my_init(void)
{
struct proc_dir_entry *file;
int ret;// allocate & init proc_head
gp_head = (struct proc_head *)kzalloc(sizeof(*gp_head), GFP_KERNEL);
if (NULL == gp_head)
{
ret = -ENOMEM;
goto err_kzalloc;
}
gp_head->item_count = 0;
gp_head->str_count = 0;
INIT_LIST_HEAD(&gp_head->lhead);// create "/proc/proc_seq" file
file = proc_create_data(
"proc_seq",// name
0666,// mode
NULL,// parent dir_entry
&proc_seq_fops,// file_operations
NULL// data
);
if (NULL == file)
{
printk("Count not create /proc/proc_seq file!\n");
ret = -1;
goto err_proc_create_data;
}return 0;err_proc_create_data:
kfree(gp_head);
err_kzalloc:
return ret;
}static void __exit my_exit(void)
{
struct proc_item *tmp1, *tmp2;remove_proc_entry("proc_seq", NULL);
list_for_each_entry_safe(tmp1, tmp2, &gp_head->lhead,litem)
{
list_del(&tmp1->litem);
kfree(tmp1->buf);
kfree(tmp1);
}
kfree(gp_head);
}module_init(my_init);
module_exit(my_exit);MODULE_AUTHOR("aran");
MODULE_LICENSE("GPL");
Makefile文件:
obj-m:= proc_test04.o
KERNEL:= /lib/modules/`uname -r`/build #for mint/ubuntu
#KERNEL:= /lib/modules/`uname -r`/source #for redhatall:
make -C $(KERNEL) M=`pwd` modulesinstall:
make -C $(KERNEL) M=`pwd` modules_install
depmod -Aclean:
make -C $(KERNEL) M=`pwd` clean
測试结果:







