proc文件系统是一种用户态检查内核状态的机制,内容动态创建,存在内存中,在驱动中用于导出驱动的部分信息而存在。
一、
apm:高级电源管理信息
bus:总线及总线上的设备
devices:可用的设备信息
driver:已经启动的驱动程序
interrupts:中断信息
ioports:端口使用信息
version:内核版本
二、
proc文件的内核描述:
struct proc_dir_entry{
.......
read_proc_t *read_proc;//读回调函数
write_proc_t *write_proc;//写回调函数
.............
}
三、proc文件的创建
三一、直接创建操作
1.创建文件
struct proc_dir_entry *create_proc_entry(const char *name,mode_t mode, struct proc_dir_entry *parent)
name:文件名
mode:要创建的文件属性
parent:这个文件的父目录
struct proc_dir_entry *create_proc_read_entry(const char *name,mode_t mode,struct proc_dir_entry *base,read_proc_t *read_proc,void *data);
2.创建目录
struct proc_dir_entry* proc_mkdir(const char *name,struct proc_dir_entry *parent)
name:要创建的目录名
parent:这个目录的父目录
3. 删除文件、目录
void remove_proc_entry(const char *name ,struct proc_dir_entry *parent)
name:要删除的文件或目录名
parent:所在的父目录
4 读操作函数原型
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:一般不使用
5.写操作
int write_func(struct file *file,const char *buffer,unsigned long count,void *data)
file:该proc文件对应的file结构,一般忽略
buffer:待写得数据所在的位置
count:待写数据的大小
data:一般不使用
6 实现流程
(1)调用create_proc_entry创建一个struct proc_dir_entry
(2)对创建的struct proc_dir_entry进行赋值:read_proc,mode,owner,size,write_proc等。
7
例子1:
#define __KERNEL__
#define MODULE
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/proc_fs.h>
#define procfs_name "proctest" //proc文件名
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);//创建proc文件,NULL表示/proc文件下
if(Our_Proc_File ==NULL)
{
remove_proc_entry(procfs_name,NULL);
printk(KERN_ALERT"Error:Cound not initialize /proc/%s\n",procfs_name);
return -ENOMEM;
}
//给proc结构赋值
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);
Makefile文件:
VER=$(shell uname -r)
obj-m:=proc1.o
build:proc1
proc1:
make -C /lib/modules/$(VER)/build M=$(CURDIR) modules
clean:
make -C /lib/modules/$(VER)/build M=$(CURDIR) clean
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
static struct proc_dir_entry *mydir;
static struct proc_dir_entry *pfile;
static char msg[255];
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) //_init表示初始化代码段
{
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(void)
{
remove_proc_entry("pool", mydir);
remove_proc_entry("mydir", NULL);
}
module_init(myproc_init);
module_exit(myproc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LMJ");
Makefile文件:
VER=$(shell uname -r)
obj-m:=proc.o
build:proc
proc:
make -C /lib/modules/$(VER)/build M=$(CURDIR) modules
clean:
make -C /lib/modules/$(VER)/build M=$(CURDIR) clean
三二、通过seq_file接口操作proc文件
1. 包含<linux/seq_file.h>头文件创建
static struct seq_operations my_seq_ops{
.start = my_seq_start,
.next = my_seq_next,
.stop = my_seq_stop,
.show = my_seq_show,
};
并实现my_seq_start、my_seq_nex、my_seq_stop、my_seq_show等函数
2. 实现一个文件的操作集结构
static struct file_operation my_proc_ops{
.ower = THIS_MODULE,
.open = my_proc_open,//需要自己实现
.read = seq_read,//直接调用系统函数
.llseek = seq_lseek,//直接调用系统函数
.release = seq_release
};
static int my_proc_open(struct inode *inode, struct file *file)
{
return seq_open(file,&my_seq_ops);
}
3. 创建proc文件
entry = create_proc_entry("my_seq",0,NULL);
if(entry)
{
entry->proc_fops = &my_proc_ops;
}