嵌入式linux之/proc文件系统(介绍加实例验证)

/proc文件系统介绍

/proc文件系统是一种特殊的、由软件创建的文件系统,内核使用它向外界导出信息。/proc下面的每一个文件都绑定于一个内核函数,用户读取其中的文件时,该函数动态地生成文件的“”内容“”

比如:通过/proc/meminfo,查询当前内存的使用情况。
在这里插入图片描述

简言之:proc文件系统时一种在用户态检查内核状态的机制。
/proc文件下的常见子目录

子目录/文件名 内容描述
apm 高级电源管理信息
bus 总线以及总线上的设备
devices 可用的设备信息
driver 已经启用的驱动程序
interrupts 中断信息
ioports 端口使用信息
version 内核版本

/proc文件系统特点

  • 每个文件都规定了严格的权限
    (可读?可写?哪个用户可读?哪个用户可写?)
  • 可以用文本编辑程序读取(more命令,cat命令,vi程序等)
  • 不仅可以有文件,还可以有子目录
  • 可以自己编写程序添加一个/proc目录下的问价
  • 文件的内容都是动态创建的,并不存在与磁盘上。

内核描述

proc内核描述:

	 struct proc_dir_entry
	 {
			.......
			read_proc_t *read_proc;
			write_proc_t *write_proc;
			.......
		}	

创建proc文件

struct proc_dir_entry create_proc_entry(const char *name,mode_t mode,struct proc_dir_entry parent)

**功能:**创建proc文件
参数

  • name:要创建的文件名
  • mode:要创建的文件的属性 默认0755
  • parent:这个文件的父目录

创建目录

*struct proc_dir_entry * proc_mkdir(const char *name,struct proc_dir_entry parent)
功能:创建proc目录
参数

  • name:要创建的目录名
  • parent:这个目录的父目录

删除目录/文件

void remove_proc_entry(const char *name,struct proc_dir_entry *parent)
功能:删除proc目录或文件
参数

  • name:要删除的文件或目录名
  • parent:所在的父目录

读写

为了能让用户读写添加的proc问价,需要挂接上读写回调函数:
read_proc
write_proc

(1)读操作

*int read_func(char *buffer,char **stat,off_t off,int count,int *peof,void data)
参数

  • buffer:把要返回给用户的信息写在buffer里,最大不超过PAGE_SIZE
  • stat:一般不使用
  • off:偏移量
  • count:用户要读取的字节数
  • peof:读到文件尾时,需要把*peof置1
  • data:一般不使用

(2)写操作

*int write_func(struct file *file,const char *buffer,unsigned long count,void data)

参数

  1. file:该proc文件对应的file结构,一般忽略
  2. buffer:待写的数据所在位置
  3. count:待写数据的大小
  4. data:一般不使用

实现流程

实现一个proc文件的流程:

  1. 调用create_proc_entry创建一个struct proc_dir_entry。
  2. 对创建的struct proc_dir_entry进行赋值:read_proc,mode,owner,size,write_proc等。

mini6410下的实例代码

(1)proc.c

		#include <linux/module.h>
		#include <linux/kernel.h>
		#include <linux/init.h>
		#include <linux/proc_fs.h>
		
		#define procfs_name "proctest"
		
		struct proc_dir_entry *Our_Proc_File;
		
		int procfile_read(char *buffer,
		                char **buffer_location,
		                off_t offset,int buffer_length,int *eof,void *data)
		{
		        int ret;
		
		        ret = sprintf(buffer,"HelloWorld\n");
		        return ret;
		}
		
		int proc_init()
		{
		        Our_Proc_File = create_proc_entry(procfs_name,0644,NULL);
		        if(Our_Proc_File == NULL)
                {
		                remove_proc_entry(procfs_name,NULL);
		                printk(KERN_ALERT "Error:Counld not initialize /proc/%s\n",procfs_name);
		                return -ENOMEM;
		        }
		
		        Our_Proc_File->read_proc = procfile_read;
		        Our_Proc_File->owner = THIS_MODULE;
		        Our_Proc_File->mode = S_IFREG | S_IRUGO;
		        Our_Proc_File->uid = 0;
		        Our_Proc_File->gid = 0;
		        Our_Proc_File->size = 37;
		        printk("/proc/%s created\n",procfs_name);
		        return 0;
		}

		void proc_exit()
		{
		        remove_proc_entry(procfs_name,NULL);
		        printk(KERN_INFO "/proc/%s removed\n",procfs_name);
		}
		
		module_init(proc_init);
		module_exit(proc_exit);


(2) Makefile

		ifneq ($(KERNELRELEASE),)

		obj-m := proc.o 
		
		else
		
		KDIR := /home/zhangbin/mini6410/linux-2.6.38 
		all:
		        make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-
		clean:
		        rm -f *.ko *.o *.mod.c *.symvers
		
		endif

(3)在mini6410板子上的运行效果

在这里插入图片描述

在/proc下先创建目录后创建文件

(1)proc1.c

		#include <linux/module.h>
		#include <linux/init.h>
		#include <linux/proc_fs.h>
		#include <asm/uaccess.h>
		
		static char msg[255];
		struct proc_dir_entry *pfile;
		static char *mydir;
		
		static int myproc_read(char *page,char **start,off_t off,int count,int *eof,void *data){
		        int len = strlen(msg);
		
		        if(off >= len)
		                return 0;
		
		        if(count > len - off)
		                count = len - off;
		
		        memcpy(page+off,msg+off,count);
		        return off + count;
		}

		static int myproc_write(struct file *file,const char __user *buffer,unsigned long count,void *data)
		{
		        unsigned long count2 = count;
		
		        if(count2 >= sizeof(msg))
		                count2 = sizeof(msg) - 1;
		
		        if(copy_from_user(msg,buffer,count2))
		                return -EFAULT;
		
		        msg[count2] = '\0';
		        return count;
		}

		static int __init myproc_init(void)
		{
		        mydir = proc_mkdir("mydir",NULL);
		        if(!mydir)
		        {
		                printk(KERN_ERR "can't create /proc/mydir\n");
		                return -1;
		        }
		
		        pfile = create_proc_entry("pool",0666,mydir);
		        if(!pfile)
		        {
		                printk(KERN_ERR "can't create /proc/mydir/pool\n");
		                remove_proc_entry("mydir",NULL);
		                return -1;
		        }
		
		        pfile->read_proc = myproc_read;
		        pfile->write_proc = myproc_write;
		
		        return 0;
		}

		static void __exit myproc_exit()
		{
		        remove_proc_entry("pool",mydir);
		
		        remove_proc_entry("mydir",NULL);
		}
		
		module_init(myproc_init);
		module_exit(myproc_exit);

(2)Makefile

	ifneq ($(KERNELRELEASE),)

		obj-m := proc1.o 
		
		else
		
		KDIR := /home/zhangbin/mini6410/linux-2.6.38 
		all:
		        make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-
		clean:
		        rm -f *.ko *.o *.mod.c *.symvers
		
		endif

(3)在mini6410开发板上验证如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41782149/article/details/89357083