标签:驱动开发 内核 链表 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 redhat all: make -C $(KERNEL) M=`pwd` modules install: make -C $(KERNEL) M=`pwd` modules_install depmod -A clean: make -C $(KERNEL) M=`pwd` clean测试结果:
ubuntu/linux mint 创建proc文件的三种方法(四),布布扣,bubuko.com
ubuntu/linux mint 创建proc文件的三种方法(四)
标签:驱动开发 内核 链表 linux mint proc
原文地址:http://blog.csdn.net/a_ran/article/details/37630135