linux内核源码分析之proc文件系统(二)
proc文件系统的实例先看一下在proc注册的目录 procfs_example,在此目录下建立了bar,foo,jiffies文件以及一个软连接jiffies_too(base) root@ubuntu:/proc/procfs_example# ls -ltotal 0-r--r--r-- 1 root root 0 Mar 25 06:50 bar-r--r--r-- 1 root root
·
目录
内核提供proc文件系统注册的源码
1、功能介绍
在proc注册的目录 procfs_example,在此目录下建立了bar,foo,jiffies文件以及一个软连接jiffies_too,目录结构如下:
(base) root@ubuntu:/proc/procfs_example# ls -l
total 0
-r--r--r-- 1 root root 0 Mar 25 06:50 bar
-r--r--r-- 1 root root 0 Mar 25 06:50 foo
-r--r--r-- 1 root root 0 Mar 25 06:50 jiffies
lrwxrwxrwx 1 root root 7 Mar 25 06:50 jiffies_too -> jiffies
查看文件内容信息
(base) root@ubuntu:/proc/procfs_example# cat bar
bar='bar'
(base) root@ubuntu:/proc/procfs_example# cat foo
foo='foo'
(base) root@ubuntu:/proc/procfs_example# cat jiffies
jiffies=4300908124
(base) root@ubuntu:/proc/procfs_example# cat jiffies
jiffies=4300908884
(base) root@ubuntu:/proc/procfs_example# cat jiffies_too
jiffies=4300917124
修改bar,foo内容并查看
(base) root@ubuntu:/proc/procfs_example# echo "good" > bar
(base) root@ubuntu:/proc/procfs_example# cat bar
bar='good'
(base) root@ubuntu:/proc/procfs_example# echo "good" > foo
(base) root@ubuntu:/proc/procfs_example# cat foo
foo='good'
软连接修改出现错误,源码中有给出原因(没有实现对应的写函数)
(base) root@ubuntu:/proc/procfs_example# echo "good" > jiffies_too
-bash: echo: write error: Input/output error
(base) root@ubuntu:/proc/procfs_example# echo "good" > jiffies
-bash: echo: write error: Input/output error
2、源码实现框架
源码实现框架。以模块的方式实现,与驱动程序模式一样
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <asm/switch_to.h>
#include <generated/autoconf.h>
#include <linux/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 ssize_t read_jiffies_proc(struct file *filp,char __user *buf,size_t count,loff_t *offp ){
copy_to_user(buf, tempstring, count);
return count;
}
//只有读
static const struct file_operations jiffies_proc_fops={
.read=read_jiffies_proc
};
static ssize_t read_foo_proc(struct file *filp,char __user *buf,size_t count,loff_t *offp ) {
//使用cat 查看文件 调用copy_to_user
//tempstr为数据内容
copy_to_user(buf, tempstr, count);
return count;
}
static ssize_t write_foo_proc(struct file *filp,const char __user *buf,size_t count,loff_t *offp ){
//命令行使用echo写入数据 调用copy_from_user
copy_from_user(foo_data.value, buf, len)
}
//读写都有
static const struct file_operations foo_proc_fops={
.read=read_foo_proc,
.write=write_foo_proc
};
static int __init init_procfs_example(void){
int rv=0;
//创建目录
example_dir=proc_mkdir("procfs_example", NULL);
//在procfs_example目录下创建jiffies,并注册文件操作jiffies_proc_fops
jiffies_file=proc_create("jiffies", 0444, example_dir, &jiffies_proc_fops);
//在procfs_example目录下创建foo,并注册文件操作foo_proc_fops
foo_file=proc_create("foo", 0, example_dir, &foo_proc_fops);
//在procfs_example目录下创建软连接jiffies_too,并连接到jiffies文件
symlink=proc_symlink("jiffies_too", example_dir, "jiffies");
return 0;
}
static void __exit cleanup_procfs_example(void){
remove_proc_entry("jiffies_too", example_dir);
remove_proc_entry("bar", example_dir);
remove_proc_entry("jiffies", example_dir);
remove_proc_entry("procfs_example", NULL);
}
module_init(init_procfs_example);
module_exit(cleanup_procfs_example);
MODULE_AUTHOR("wyong");
MODULE_DESCRIPTION("proc filesystem demo");
proc提供的函数:
- proc_mkdir 创建目录,并挂载到/proc上
- proc_create 创建文件,访问权限可以显示确定
- proc_symlink 生成一个符号链接。
- 从proc目录中删除一个动态生成的数据项
3、源码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <asm/switch_to.h>
#include <generated/autoconf.h>
#include <linux/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;
int foo_len,foo_temp,bar_len,bar_temp;
int jiff_temp=-1;
char tempstr[FOOBAR_LEN*2+5];
static ssize_t read_jiffies_proc(struct file *filp,char __user *buf,size_t count,loff_t *offp ){
printk(KERN_INFO"count=%d jiff_temp=%d\n", count, jiff_temp);
char tempstring[100]="";
if (jiff_temp!=0)
jiff_temp=sprintf(tempstring, "jiffies=%ld\n", jiffies);
if (count>jiff_temp)
count=jiff_temp;
jiff_temp=jiff_temp-count;
printk(KERN_INFO"count=%d jiff_temp=%d\n", count, jiff_temp);
copy_to_user(buf, tempstring, count);
if (count==0)
jiff_temp=-1;
return count;
}
static const struct file_operations jiffies_proc_fops={
.read=read_jiffies_proc
};
static ssize_t read_foo_proc(struct file *filp,char __user *buf,size_t count,loff_t *offp ) {
printk(KERN_INFO"count=%d\n", count);
if (count>foo_temp)
count=foo_temp;
foo_temp=foo_temp-count;
strcpy(tempstr, foo_data.name);
strcat(tempstr, "='");
strcat(tempstr, foo_data.value);
strcat(tempstr, "'\n");
printk(KERN_INFO"count=%d length(tempstr)=%d\n", count, strlen(tempstr));
copy_to_user(buf, tempstr, count);
if (count==0)
foo_temp=foo_len+4;
return count;
}
static ssize_t write_foo_proc(struct file *filp,const char __user *buf,size_t count,loff_t *offp ){
int len;
if (count>FOOBAR_LEN)
len=FOOBAR_LEN;
else
len=count;
if (copy_from_user(foo_data.value, buf, len))
return -EFAULT;
foo_data.value[len-1]='\0';
foo_len=strlen(foo_data.name)+strlen(foo_data.value);
foo_temp=foo_len+4;
return len;
}
static const struct file_operations foo_proc_fops={
.read=read_foo_proc,
.write=write_foo_proc
};
static ssize_t read_bar_proc(struct file *filp,char __user *buf,size_t count,loff_t *offp ) {
printk(KERN_INFO"count=%d\n", count);
if (count>bar_temp)
count=bar_temp;
bar_temp=bar_temp-count;
strcpy(tempstr, bar_data.name);
strcat(tempstr, "='");
strcat(tempstr, bar_data.value);
strcat(tempstr, "'\n");
printk(KERN_INFO"count=%d length(tempstr)=%d\n", count, strlen(tempstr));
copy_to_user(buf, tempstr, count);
if (count==0)
bar_temp=bar_len+4;
return count;
}
static ssize_t write_bar_proc(struct file *filp,const char __user *buf,size_t count,loff_t *offp ){
int len;
if (count>FOOBAR_LEN)
len=FOOBAR_LEN;
else
len=count;
if (copy_from_user(bar_data.value, buf, len))
return -EFAULT;
bar_data.value[len-1]='\0';
bar_len=strlen(bar_data.name)+strlen(bar_data.value);
bar_temp=bar_len+4;
return len;
}
static const struct file_operations bar_proc_fops={
.read=read_bar_proc,
.write=write_bar_proc
};
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;
}
jiffies_file=proc_create("jiffies", 0444, example_dir, &jiffies_proc_fops);
if (jiffies_file==NULL){
rv=-ENOMEM;
goto no_jiffies;
}
strcpy(foo_data.name, "foo");
strcpy(foo_data.value, "foo");
foo_len=strlen(foo_data.name)+strlen(foo_data.value);
foo_temp=foo_len+4;
foo_file=proc_create("foo", 0, example_dir, &foo_proc_fops);
if (foo_file==NULL){
rv=-ENOMEM;
goto no_foo;
}
strcpy(bar_data.name, "bar");
strcpy(bar_data.value, "bar");
bar_len=strlen(bar_data.name)+strlen(bar_data.value);
bar_temp=bar_len+4;
bar_file=proc_create("bar", 0, example_dir, &bar_proc_fops);
if (bar_file==NULL){
rv=-ENOMEM;
goto no_bar;
}
symlink=proc_symlink("jiffies_too", example_dir, "jiffies");
if (symlink==NULL){
rv=-ENOMEM;
goto no_symlink;
}
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_AUTHOR("Zhang Le");
MODULE_DESCRIPTION("proc filesystem example");
在下一篇文章中介绍具体的实现
参考:
《深入理解linux内核》
《Linux内核深度解析》
更多推荐
已为社区贡献12条内容
所有评论(0)