2009年11月24日 星期二

[轉貼]使用/proc文件系統的一個簡單例子

[轉貼]使用/proc文件系統的一個簡單例子

kernel:2.6.28

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h>

#define MODULE_VERS "1.0"
#define MODULE_NAME "procfs_example"
#define FOOBAR_LEN 8

struct fb_data_t {
char name[FOOBAR_LEN + 1];
char value[FOOBAR_LEN + 1];
};
static struct proc_dir_entry *example_dir,*foo_file,\
*bar_file,*jiffies_file,*symlink;
struct fb_data_t foo_data,bar_data;

//A read callback function for jiffies file
static int proc_read_jiffies(char *page,char **stat,\
off_t off,int count,int *eof,void *data)
{
int len;

len = sprintf(page,"jiffies = %ld\n",jiffies); //jiffies is used as
//the time counter of in the Kernal
return len;
}
//A read callback function
static int proc_read_foobar (char *page,char **stat,\
off_t off,int count,int *eof,void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *) data;
len = sprintf(page,"%s = '%s'\n",fb_data->name,fb_data->value);
return len;
}

//A write callback function for foobar_file
static int proc_write_foobar (struct file *file,const char *buffer,\
unsigned long count,void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *)data;
if(count > FOOBAR_LEN)
len = FOOBAR_LEN;
else
len = count;
/*For buffer not exist in memory,so must copy it into Kernal first*/
if(copy_from_user(fb_data->value,buffer,len))
return -EFAULT;
fb_data->value[len] = '\0';
return len;
}

//init the MODULE
static int __init init_procfs_example(void)
{
int rv = 0;
/*create directory*/
example_dir = proc_mkdir(MODULE_NAME,NULL);
/*handle the error*/
if(example_dir == NULL){
rv = -ENOMEM;
goto out;
}
example_dir->owner = THIS_MODULE;
/*create jiffies using convenience function*/
jiffies_file = create_proc_read_entry("jiffies",0444,example_dir,\
proc_read_jiffies,NULL);
if(jiffies_file == NULL){
rv = -ENOMEM;
goto no_jiffies;
}
jiffies_file->owner = THIS_MODULE;
/*creat foo and bar files using same callback functions*/
foo_file = create_proc_entry("foo",0644,example_dir);
if(foo_file == NULL){
rv = -ENOMEM;
goto no_foo;
}
strcpy(foo_data.name,"foo");
strcpy(foo_data.value,"foo");
foo_file->data = &foo_data;
foo_file->read_proc = proc_read_foobar;
foo_file->write_proc = proc_write_foobar;
foo_file->owner = THIS_MODULE;

bar_file = create_proc_entry("bar",0644,example_dir);
if(bar_file == NULL){
rv = -ENOMEM;
goto no_bar;
}
strcpy(bar_data.name,"bar");
strcpy(bar_data.value,"bar");
bar_file->data = &bar_data;
bar_file->read_proc = proc_read_foobar;
bar_file->write_proc= proc_write_foobar;
bar_file->owner = THIS_MODULE;

/*create symlink*/
symlink = proc_symlink("jiffies_too",example_dir,"jiffies");
if(symlink == NULL){
rv = -ENOMEM;
goto no_symlink;
}

symlink->owner = THIS_MODULE;

printk(KERN_INFO "%s %s initialised\n",MODULE_NAME,MODULE_VERS);
return 0;

no_symlink:
remove_proc_entry("symlink",example_dir);
no_bar:
remove_proc_entry("bar",example_dir);
no_foo:
remove_proc_entry("foo",example_dir);
no_jiffies:
remove_proc_entry(MODULE_NAME,NULL);;
out:
return rv;
}

static void __exit cleanup_procfs_example(void)
{
remove_proc_entry("jiffies_too",example_dir);
remove_proc_entry("bar",example_dir);
remove_proc_entry("foo",example_dir);
remove_proc_entry("jiffies",example_dir);
remove_proc_entry(MODULE_NAME,NULL);

printk(KERN_INFO "%s %s removed\n",MODULE_NAME,MODULE_VERS);

}
module_init(init_procfs_example);
module_exit(cleanup_procfs_example);


ref : 使用/proc文件系統的一個簡單例子

沒有留言:

張貼留言