> 文档中心 > linux内核源码分析之proc文件系统(二)

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 0 Mar 25 06:50 foo-r--r--r-- 1 root root 0 Mar 25 06:50 jiffieslrwxrwxrwx 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 jiffiesjiffies=4300908124(base) root@ubuntu:/proc/procfs_example# cat jiffiesjiffies=4300908884(base) root@ubuntu:/proc/procfs_example# cat jiffies_toojiffies=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

源码实现框架

源码实现框架。以模块的方式实现,与驱动程序模式一样

#include #include #include #include #include #include #include #include #include #define MODULE_VERS "1.0"#define MODULE_NAME "procfs_example"#define FOOBAR_LEN 8struct 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_usercopy_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_fopsjiffies_file=proc_create("jiffies", 0444, example_dir, &jiffies_proc_fops);//在procfs_example目录下创建foo,并注册文件操作foo_proc_fopsfoo_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目录中删除一个动态生成的数据项

源码

#include #include #include #include #include #include #include #include #include #define MODULE_VERS "1.0"#define MODULE_NAME "procfs_example"#define FOOBAR_LEN 8struct 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;elselen=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;elselen=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内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂