这个例子使用了内核模块,在/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
两者一样。
阅读(5398) | 评论(1) | 转发(0) |