使用proc函数的实例

来源:互联网 发布:全能淘客cms 编辑:程序博客网 时间:2024/06/05 08:55

这个例子使用了内核模块,在/proc目录下创建一个名叫procfs_example的目录,并且在该目录下创建三个普通文件和一个软连接。一个文件名叫foo,只读,内容为foo = 'foo';一个文件名叫bar只读,内容为bar ='bar';一个叫jiffies,只读,它会动态地显示jiffies的值。软连接名叫jiffies_too,它是对文件jiffies的软连接。
以下是实验内容:
lzel@lzel-desktop:~/works/proc$ ls
Makefile  procfs_example.c
lzel@lzel-desktop:~/works/proc$ cat procfs_example.c
#include <linux/module.h>
#include <linux/kernel.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;

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

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;
    if (copy_from_user(fb_data->value,buffer,len))
        return -EFAULT;
    fb_data->value[len] = '/n';
    return len;
}
static int __init init_procfs_example (void)
{
    int rv = 0;

    example_dir = proc_mkdir (MODULE_NAME,NULL);
    if (example_dir == NULL)
    {
        rv = -ENOMEM;
        goto out;
    }
    example_dir->owner = THIS_MODULE;
    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;
    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;

    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("bar",example_dir);
    no_bar:
        remove_proc_entry ("foo",example_dir);
    no_foo:
        remove_proc_entry ("jiffies",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);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("lzel");
MODULE_DESCRIPTION("procfs examples");

lzel@lzel-desktop:~/works/proc$ cat Makefile
TARGET=procfs_example
KERNEL=`uname -r`
#KDIR = /usr/src/linux-headers-$(KERNEL)
KDIR = /usr/src/kernels/2.6.18-194.el5-i686/
PWD = `pwd`
obj-m:=$(TARGET).o
default:
        make -C $(KDIR) M=$(PWD) modules
clean:
        make -C $(KDIR) M=$(PWD) clean
lzel@lzel-desktop:~/works/proc$ sudo make
[sudo] password for lzel:
make -C /usr/src/linux-headers-`uname -r` M=`pwd` modules
make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.24-21-generic'
  CC [M]  /home/lzel/works/proc/procfs_example.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/lzel/works/proc/procfs_example.mod.o
  LD [M]  /home/lzel/works/proc/procfs_example.ko
make[1]:正在离开目录 `/usr/src/linux-headers-2.6.24-21-generic'
lzel@lzel-desktop:~/works/proc$ ls
procfs_example.c   procfs_example.ko     procfs_example.mod.o  procfs_example.o
Makefile  Module.symvers   procfs_example.mod.c       
lzel@lzel-desktop:~/works/proc$ sudo insmod procfs_example.ko
lzel@lzel-desktop:~/works/proc$ lsmod |head
Module                  Size  Used by
procfs_example          4024  0
ipv6                  267780  10
af_packet              23812  2
rfcomm                 41744  2
l2cap                  25728  13 rfcomm
bluetooth              61156  4 rfcomm,l2cap
ppdev                  10372  0
cpufreq_conservative     8712  0
cpufreq_ondemand        9740  0
lzel@lzel-desktop:~/works/proc$ dmesg |tail
[   72.183969] Bluetooth: RFCOMM socket layer initialized
[   72.184566] Bluetooth: RFCOMM TTY layer initialized
[   72.184593] Bluetooth: RFCOMM ver 1.8
[   75.149946] NET: Registered protocol family 17
[   83.211043] NET: Registered protocol family 10
[   83.222138] lo: Disabled Privacy Extensions
[   94.443153] eth1: no IPv6 routers present
[ 4620.210470] procfs_example 1.0 initialised //初始化完成
lzel@lzel-desktop:~/works/proc$
现在到/proc中去看看,是不是如我们所设想的一样呢。
lzel@lzel-desktop:~/works/proc$ ls /proc/|grep procfs_example
procfs_example //果然有procfs_example目录,这样就让我们进入到这个目录去验证其他的文件
lzel@lzel-desktop:~/works/proc$ cd /proc/procfs_example/
lzel@lzel-desktop:/proc/procfs_example$ ll //确实有三个普通文件和一个软连接
总用量 0
-rw-r--r-- 1 root root 0 2008-10-11 20:23 bar
-rw-r--r-- 1 root root 0 2008-10-11 20:23 foo
-r--r--r-- 1 root root 0 2008-10-11 20:23 jiffies
lrwxrwxrwx 1 root root 7 2008-10-11 20:23 jiffies_too -&gt; jiffies
lzel@lzel-desktop:/proc/procfs_example$ cat bar //查看bar
bar = 'bar'
lzel@lzel-desktop:/proc/procfs_example$ cat foo //查看foo
foo = 'foo'
lzel@lzel-desktop:/proc/procfs_example$ cat jiffies //查看jiffies
jiffies = 1153731
lzel@lzel-desktop:/proc/procfs_example$ cat jiffies_too //查看软连接
jiffies = 1158238
lzel@lzel-desktop:/proc/procfs_example$
细心的读者也许看到了,两个jiffies的值是不同的。因为jiffies是内核中的一个全局变量,用来记录自系统启动以来产生的节拍数。它自从开机以来就一刻不停的增长着。所以可以用jiffies/tick_rate 来计算计算运行了多长时间。jiffies定义在文件<linux/jiffies.h>中:

extern unsigned long volatile jiffies;

我们可以用一下命令动态地查看jiffies的变化情况:
lzel@lzel-desktop:/proc/procfs_example$ watch cat jiffies
或者
lzel@lzel-desktop:/proc/procfs_example$ watch cat jiffies_too
两者一样。

原创粉丝点击