zoukankan      html  css  js  c++  java
  • 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
    ", 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!
    ");
    		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
    測试结果:


  • 相关阅读:
    Roadblocks(poj 3255)
    最小集合(51nod 1616)
    绿色通道(codevs 3342)
    解的个数(codevs 1213)
    多米诺(codevs 3052)
    abcd
    dwarf tower
    第K 小数
    noip2016复习
    文化之旅(洛谷 1078)
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3933585.html
Copyright © 2011-2022 走看看