Chinaunix首页 | 论坛 | 博客
  • 博客访问: 217590
  • 博文数量: 27
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 360
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-14 17:06
文章分类

全部博文(27)

文章存档

2011年(1)

2009年(5)

2008年(21)

我的朋友

分类: LINUX

2008-10-12 16:34:53

这个例子使用了内核模块,在/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
#include
#include
#include
#include
#include

#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)
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 -> 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定义在文件中:

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
两者一样。
阅读(5411) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-10-13 15:24:32

这个例子比较典型,抽时间给大家讲讲。