现在的位置: 首页 > 综合 > 正文

procfs简介

2013年08月07日 ⁄ 综合 ⁄ 共 2379字 ⁄ 字号 评论关闭

1. 简介

     procfs文件系统(/proc)在linux内核中算是一个比较特殊的文件系统。它是一个虚拟的文件系统:它并没有关联到具体的块设备,而是存在于内存中。procfs中的文件存在的目的在于允许用户程序从内核获取信息(例如proc目录下以数字开头的文件)以及debug程序(如/proc/ksyms.

    本文介绍procfs文件系统在linux 内核的使用。首先介绍所有用于管理procfs文件系统文件的函数。然后介绍与用户程序的交互和某些技巧。最后展示一个完整的例子。

注意:/proc/sys目录下的文件是sysctl文件。他们不属于procfs,由完全不同的API管理(参见其他kernel api的相关书籍)

2.管理procfs

     这部分介绍内核空间在procfs目录下中创建文件、符号链接、设备节点和目录所用到的函数。

注意: 必须包含头文件:

        #include <linux/proc_fs.h>
创建常规文件:

struct proc_dir_entry* create_proc_entry(

const char* name,

 

mode_t mode,

 

struct proc_dir_entry* parent;

该函数用于在目录parent下创建名叫name的常规文件,访问权限由mode指定。 parent NULL则在/procfs目录下创建文件。 成功时,函数返回指向新创建的结构体 struct  proc_dir_entry的指针,失败返回NULL。文章的第三部分将介绍对新创建的文件的一些操作。

 

注意: 你可以传递一个多级目录,例如 create_proc_entry("dirvers/via0/info") 必要时会以权限0755创建via0目录。

如果想创建只读文件,则可以考虑使用函数create_proc_read_entry来一次性创建并初始化procfs项。

创建符号链接

struct proc_dir_entry* proc_symlink(

const char* name,

 

struct proc_dir_entry* parent,

 

const char* dest);

该函数在目录prarent下创建指向dest的符号链接name。相当于用户模式的:ln -s

 

创建目录

struct proc_dir_entry* proc_mkdir(

const char* name,

 

struct proc_dir_entry* parent);

 

该函数在parent目录下创建目录name

删除项

void remove_proc_entry(

const char* name,

 

struct proc_dir_entry* parent);

该函数在procfs系统的parent目录下删除name 节点通过名字来删除,而不是通过创建时返回的proc_dir_entry结构体。本函数并不递归删除项目

注意: 必须在调用remove_proc_entry之前释放掉相对应的结构体struct proc_dir_enrty

3.用户进程交互

procfs文件系统不直接从内核内存中读写数据,而是使用文件的回调函数:当特定文件被读写时嗦调用的函数。这些函数必须在procfs文件创建以后通过设置结构体struct proc_dir_entry(由create_proc_entry函数返回) 中的read_procwrite_proc字段来进行初始化。示例代码如下:

struct proc_dir_entry* entry;

entry->read_proc = read_proc_foo;

entry->write_proc = write_proc_foo;

如果仅使用read_proc.则可以考虑使用函数create_proc_read_entry来一次性创建并初始化procfs项。

 

读取数据:

read函数是允许用户程序从内核中读取数据的回调函数,它的声明如下:

int read_func(

char* buffer,

 

char** start,

 

off_t off,

 

int count,

 

int* peof,

 

void* data);

read函数把它所提供的信息吸入buffer指向的内存,这块内存的大小为PAGE_SIZE

*peof置为1用作到达文件结尾的标识。

参数data可以被用来创建为多个文件创建同一个回调函数。

函数返回值金和剩余参数在文件fs/proc/generic.c的注释中有所描述,这些描述如下:

*start置为NULL(默认就这样)。将请求的数据写到buffer 返回世界写入的字节数

 

写入数据

写回调函数允许用户程序向内核写入数据,因此可以控制内核的部分。写函数的声明如下:

int write_func(

struct file* file,

 

const char* buffer,

 

unsigned long count,

 

void* data);

 

写回调函数从buffer中读取count字节。注意buffer并不在内核内存空间中,所以必须先用copy_from_user拷贝到内科空间,参数file通常被忽略。文章的第五部分有例子。

为多个文件建立单个回调函数

当存在大量几乎相等的文件的时候,为每个文件建立单独的回调函数就很不方便。更好的办法是为这些文件使用同一个回调函数,而这个回调函数通过结构体proc_dir_entrydata字段来区分不通的文件。首先,应该初始化data字段:

struct proc_dir_entry* entry;

struct my_file_data *file_data;

file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);

entry->data = file_data;

data字段的类型是void*

抱歉!评论已关闭.